You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2020/08/25 07:39:10 UTC

[logging-log4j2] 02/02: #335 Migrate JsonTemplateLayout manual from Xdoc to AsciiDoc.

This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 20d5463ab4114b12c4c95a8704fd5cbabfc17949
Author: Volkan Yazıcı <vo...@gmail.com>
AuthorDate: Tue Aug 25 09:22:00 2020 +0200

    #335 Migrate JsonTemplateLayout manual from Xdoc to AsciiDoc.
---
 ...te-layout.adoc => json-template-layout.adoc.vm} |  344 ++---
 src/site/xdoc/manual/json-template-layout.xml.vm   | 1526 --------------------
 2 files changed, 177 insertions(+), 1693 deletions(-)

diff --git a/src/site/asciidoc/manual/json-template-layout.adoc b/src/site/asciidoc/manual/json-template-layout.adoc.vm
similarity index 58%
rename from src/site/asciidoc/manual/json-template-layout.adoc
rename to src/site/asciidoc/manual/json-template-layout.adoc.vm
index 1be3f5f..c2da984 100644
--- a/src/site/asciidoc/manual/json-template-layout.adoc
+++ b/src/site/asciidoc/manual/json-template-layout.adoc.vm
@@ -17,33 +17,33 @@
 = JSON Template Layout
 Volkan Yazıcı <vy...@apache.org>
 
-<code>JsonTemplateLayout</code> is a customizable, efficient, and garbage-free JSON
-emitting layout. It encodes <code>LogEvent</code>s according to the structure described
+`JsonTemplateLayout` is a customizable, efficient, and garbage-free JSON
+emitting layout. It encodes ``LogEvent``s according to the structure described
 by the JSON template provided. In a nutshell, it shines with its
 
-* Customizable JSON structure (see <code>eventTemplate[Uri]</code> and
-  <code>stackTraceElementTemplate[Uri]</code> parameters)
+* Customizable JSON structure (see `eventTemplate[Uri]` and
+  `stackTraceElementTemplate[Uri]` parameters)
 
-* Customizable timestamp formatting (see <code>timestamp</code> parameter)
+* Customizable timestamp formatting (see `timestamp` parameter)
 
 [#usage]
 == Usage
 
-Adding <code>log4j-layout-json-template</code> artifact to your list of dependencies is
-enough to enable access to <code>JsonTemplateLayout</code> in your Log4j configuration:
+Adding `log4j-layout-json-template` artifact to your list of dependencies is
+enough to enable access to `JsonTemplateLayout` in your Log4j configuration:
 
 [source,xml]
 ----
 <dependency>
     <groupId>org.apache.logging.log4j</groupId>
     <artifactId>log4j-layout-json-template</artifactId>
-    <version>${log4j.version}</version>
+    <version>${Log4jReleaseVersion}</version>
 </dependency>
 ----
 
 For instance, given the following JSON template modelling the
 https://github.com/logstash/log4j-jsonevent-layout[the official Logstash
-<code>JSONEventLayoutV1</code>] (accessible via <code>classpath:LogstashJsonEventLayoutV1.json</code>)
+`JSONEventLayoutV1`] (accessible via `classpath:LogstashJsonEventLayoutV1.json`)
 
 [source,json]
 ----
@@ -107,14 +107,14 @@ https://github.com/logstash/log4j-jsonevent-layout[the official Logstash
 }
 ----
 
-in combination with the below <code>log4j2.xml</code> configuration:
+in combination with the below `log4j2.xml` configuration:
 
 [source,xml]
 ----
 <JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/>
 ----
 
-or with the below <code>log4j2.properties</code> configuration:
+or with the below `log4j2.properties` configuration:
 
 [source,ini]
 ----
@@ -122,7 +122,7 @@ appender.console.json.type = JsonTemplateLayout
 appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.json
 ----
 
-<code>JsonTemplateLayout</code> emits JSON strings as follows:
+`JsonTemplateLayout` emits JSON strings as follows:
 
 [source,json]
 ----
@@ -149,9 +149,9 @@ appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.jso
 [#layout-config]
 == Layout Configuration
 
-<code>JsonTemplateLayout</code> is configured with the following parameters:
+`JsonTemplateLayout` is configured with the following parameters:
 
-.<code>JsonTemplateLayout</code> parameters
+.`JsonTemplateLayout` parameters
 [cols="1m,1m,4"]
 |===
 | Parameter Name
@@ -160,29 +160,29 @@ appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.jso
 
 | charset
 | Charset
-| <code>Charset</code> used for <code>String</code> encoding
+| `Charset` used for `String` encoding
 
 | locationInfoEnabled
 | boolean
-| toggles access to the <code>LogEvent</code> source; file name, line number, etc.
-  (defaults to <code>false</code> set by <code>log4j.layout.jsonTemplate.locationInfoEnabled</code>
+| toggles access to the `LogEvent` source; file name, line number, etc.
+  (defaults to `false` set by `log4j.layout.jsonTemplate.locationInfoEnabled`
   property)
 
 | stackTraceEnabled
 | boolean
-| toggles access to the stack traces (defaults to <code>true</code> set by
-  <code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property)
+| toggles access to the stack traces (defaults to `true` set by
+  `log4j.layout.jsonTemplate.stackTraceEnabled` property)
 
 | eventTemplate
 | String
-| inline JSON template for rendering <code>LogEvent</code>s (has priority over
-  <code>eventTemplateUri</code>, defaults to <code>null</code> set by
-  <code>log4j.layout.jsonTemplate.eventTemplate</code> property)
+| inline JSON template for rendering ``LogEvent``s (has priority over
+  `eventTemplateUri`, defaults to `null` set by
+  `log4j.layout.jsonTemplate.eventTemplate` property)
 
 | eventTemplateUri
 | String
-| URI pointing to the JSON template for rendering <code>LogEvent</code>s (defaults to
-  <code>classpath:EcsLayout.json</code> set by <code>log4j.layout.jsonTemplate.eventTemplateUri</code>
+| URI pointing to the JSON template for rendering ``LogEvent``s (defaults to
+  `classpath:EcsLayout.json` set by `log4j.layout.jsonTemplate.eventTemplateUri`
   property)
 
 | eventTemplateAdditionalFields
@@ -191,43 +191,43 @@ appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.jso
 
 | stackTraceElementTemplate
 | String
-| inline JSON template for rendering <code>StackTraceElement</code>s (has priority over
-  <code>stackTraceElementTemplateUri</code>, defaults to <code>null</code> set by
-  <code>log4j.layout.jsonTemplate.stackTraceElementTemplate</code> property)
+| inline JSON template for rendering ``StackTraceElement``s (has priority over
+  `stackTraceElementTemplateUri`, defaults to `null` set by
+  `log4j.layout.jsonTemplate.stackTraceElementTemplate` property)
 
 | stackTraceElementTemplateUri
 | String
-| JSON template for rendering <code>StackTraceElement</code>s (defaults to
-  <code>classpath:StackTraceElementLayout.json</code> set by
-  <code>log4j.layout.jsonTemplate.stackTraceElementTemplateUri</code> property)
+| JSON template for rendering ``StackTraceElement``s (defaults to
+  `classpath:StackTraceElementLayout.json` set by
+  `log4j.layout.jsonTemplate.stackTraceElementTemplateUri` property)
 
 | eventDelimiter
 | String
-| delimiter used for separating emitted <code>LogEvent</code>s (defaults to
-  <code>System.lineSeparator()</code> set by <code>log4j.layout.jsonTemplate.eventDelimiter</code>
+| delimiter used for separating emitted ``LogEvent``s (defaults to
+  `System.lineSeparator()` set by `log4j.layout.jsonTemplate.eventDelimiter`
   property)
 
 | nullEventDelimiterEnabled
 | boolean
-| append <code>\0</code> (<code>null</code>) character to the end of every emitted <code>eventDelimiter</code>
-  (defaults to <code>false</code> set by
-  <code>log4j.layout.jsonTemplate.nullEventDelimiterEnabled</code> property)
+| append `\0` (`null`) character to the end of every emitted `eventDelimiter`
+  (defaults to `false` set by
+  `log4j.layout.jsonTemplate.nullEventDelimiterEnabled` property)
 
 | maxStringLength
 | int
 | truncate string values longer than the specified limit (defaults to 16384 set
-  by <code>log4j.layout.jsonTemplate.maxStringLength</code> property)
+  by `log4j.layout.jsonTemplate.maxStringLength` property)
 
 | truncatedStringSuffix
 | String
-| suffix to append to strings truncated due to exceeding <code>maxStringLength</code>
-  (defaults to <code>…</code> set by <code>log4j.layout.jsonTemplate.truncatedStringSuffix</code>
+| suffix to append to strings truncated due to exceeding `maxStringLength`
+  (defaults to `…` set by `log4j.layout.jsonTemplate.truncatedStringSuffix`
   property)
 
 | recyclerFactory
 | RecyclerFactory
-| recycling strategy that can either be <code>dummy</code>, <code>threadLocal</code>, or <code>queue</code>
-  (set by <code>log4j.layout.jsonTemplate.recyclerFactory</code> property)
+| recycling strategy that can either be `dummy`, `threadLocal`, or `queue`
+  (set by `log4j.layout.jsonTemplate.recyclerFactory` property)
 |===
 
 [#additional-event-template-fields]
@@ -235,7 +235,7 @@ appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.jso
 
 Additional event template field is a convenient short-cut to add custom fields
 to a template or override the fields of a template. Following configuration
-overrides the <code>host</code> field of the <code>GelfLayout.json</code> template and adds two new
+overrides the `host` field of the `GelfLayout.json` template and adds two new
 custom fields:
 
 [source,xml]
@@ -270,30 +270,30 @@ One can also pass JSON literals into additional fields:
 [#recycling-strategy]
 === Recycling strategy
 
-<code>RecyclerFactory</code> plays a crucial role for determining the memory footprint of
+`RecyclerFactory` plays a crucial role for determining the memory footprint of
 the layout. Template resolvers employ it to create recyclers for objects that
-they can reuse. The function of each <code>RecyclerFactory</code> and when one should
+they can reuse. The function of each `RecyclerFactory` and when one should
 prefer one over another is explained below:
 
-* <code>dummy</code> performs no recycling, hence each recycling attempt will result in a
+* `dummy` performs no recycling, hence each recycling attempt will result in a
 new instance. This will obviously create a load on the garbage-collector. It
 is a good choice for applications with low and medium log rate.
 
-* <code>threadLocal</code> performs the best, since every instance is stored in
-<code>ThreadLocal</code>s and accessed without any synchronization cost. Though this
+* `threadLocal` performs the best, since every instance is stored in
+``ThreadLocal``s and accessed without any synchronization cost. Though this
 might not be a desirable option for applications running with hundreds of
 threads or more, e.g., a web servlet.
 
-* <code>queue</code> is the best of both worlds. It allows recycling of objects up to a
-certain number (<code>capacity</code>). When this limit is exceeded due to excessive
-concurrent load (e.g., <code>capacity</code> is 50 but there are 51 threads concurrently
-trying to log), it starts allocating. <code>queue</code> is a good strategy where
-<code>threadLocal</code> is not desirable.
+* `queue` is the best of both worlds. It allows recycling of objects up to a
+certain number (`capacity`). When this limit is exceeded due to excessive
+concurrent load (e.g., `capacity` is 50 but there are 51 threads concurrently
+trying to log), it starts allocating. `queue` is a good strategy where
+`threadLocal` is not desirable.
 +
-<code>queue</code> also accepts optional <code>supplier</code> (of type <code>java.util.Queue</code>, defaults to
-  <code>org.jctools.queues.MpmcArrayQueue.new</code> if JCTools is in the classpath;
-otherwise <code>java.util.concurrent.ArrayBlockingQueue.new</code>) and <code>capacity</code> (of
-type <code>int</code>, defaults to <code>max(8,2*cpuCount+1)</code>) parameters:
+`queue` also accepts optional `supplier` (of type `java.util.Queue`, defaults to
+  `org.jctools.queues.MpmcArrayQueue.new` if JCTools is in the classpath;
+otherwise `java.util.concurrent.ArrayBlockingQueue.new`) and `capacity` (of
+type `int`, defaults to `max(8,2*cpuCount+1)`) parameters:
 +
 [source]
 ----
@@ -302,26 +302,26 @@ queue:capacity=10
 queue:supplier=java.util.concurrent.ArrayBlockingQueue.new,capacity=50
 ----
 
-The default <code>RecyclerFactory</code> is <code>threadLocal</code>, if
-<code>log4j2.enable.threadlocals=true</code>; otherwise, <code>queue</code>.
+The default `RecyclerFactory` is `threadLocal`, if
+`log4j2.enable.threadlocals=true`; otherwise, `queue`.
 
 [#template-config]
 == Template Configuration
 
-Templates are configured by means of the following <code>JsonTemplateLayout</code>
+Templates are configured by means of the following `JsonTemplateLayout`
 parameters:
 
-- <code>eventTemplate[Uri]</code> (for serializing <code>LogEvent</code>s)
-- <code>stackTraceElementTemplate[Uri]</code> (for serializing <code>StackStraceElement</code>s)
-- <code>eventTemplateAdditionalFields</code> (for extending the used event template)
+- `eventTemplate[Uri]` (for serializing ``LogEvent``s)
+- `stackTraceElementTemplate[Uri]` (for serializing ``StackStraceElement``s)
+- `eventTemplateAdditionalFields` (for extending the used event template)
 
 [#event-templates]
 === Event Templates
 
-<code>eventTemplate[Uri]</code> describes the JSON structure <code>JsonTemplateLayout</code> uses to
-serialize <code>LogEvent</code>s. The default configuration (accessible by
-<code>log4j.layout.jsonTemplate.eventTemplate[Uri]</code> property) is set to
-<code>classpath:EcsLayout.json</code> provided by the <code>log4j-layout-json-template</code>
+`eventTemplate[Uri]` describes the JSON structure `JsonTemplateLayout` uses to
+serialize ``LogEvent``s. The default configuration (accessible by
+`log4j.layout.jsonTemplate.eventTemplate[Uri]` property) is set to
+`classpath:EcsLayout.json` provided by the `log4j-layout-json-template`
 artifact:
 
 [source,json]
@@ -375,34 +375,34 @@ artifact:
 
 ----
 
-<code>log4j-layout-json-template</code> artifact contains the following predefined event
+`log4j-layout-json-template` artifact contains the following predefined event
 templates:
 
-- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/EcsLayout.json[<code>EcsLayout.json</code>]
+- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/EcsLayout.json[`EcsLayout.json`]
   described by https://www.elastic.co/guide/en/ecs/current/ecs-reference.html[the Elastic Common Schema (ECS) specification]
 
-- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/LogstashJsonEventLayoutV1.json[<code>LogstashJsonEventLayoutV1.json</code>]
+- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/LogstashJsonEventLayoutV1.json[`LogstashJsonEventLayoutV1.json`]
   described in https://github.com/logstash/log4j-jsonevent-layout[Logstash
-  <code>json_event</code> pattern for log4j]
+  `json_event` pattern for log4j]
 
-- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/GelfLayout.json[<code>GelfLayout.json</code>]
+- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/GelfLayout.json[`GelfLayout.json`]
   described by https://docs.graylog.org/en/3.1/pages/gelf.html#gelf-payload-specification[the
   Graylog Extended Log Format (GELF) payload specification] with additional
-  <code>_thread</code> and <code>_logger</code> fields. (Here it is advised to override the obligatory
-  <code>host</code> field with a user provided constant via <code>eventTemplateAdditionalFields</code>
-  to avoid <code>hostName</code> property lookup at runtime, which incurs an extra cost.)
-
-- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/JsonLayout.json[<code>JsonLayout.json</code>]
-  providing the exact JSON structure generated by link:layouts.html#JSONLayout[<code>JsonLayout</code>]
-  with the exception of <code>thrown</code> field. (<code>JsonLayout</code> serializes the <code>Throwable</code>
-  as is via Jackson <code>ObjectMapper</code>, whereas <code>JsonLayout.json</code> template of
-  <code>JsonTemplateLayout</code> employs the <code>StackTraceElementLayout.json</code> template
+  `_thread` and `_logger` fields. (Here it is advised to override the obligatory
+  `host` field with a user provided constant via `eventTemplateAdditionalFields`
+  to avoid `hostName` property lookup at runtime, which incurs an extra cost.)
+
+- https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/JsonLayout.json[`JsonLayout.json`]
+  providing the exact JSON structure generated by link:layouts.html#JSONLayout[`JsonLayout`]
+  with the exception of `thrown` field. (`JsonLayout` serializes the `Throwable`
+  as is via Jackson `ObjectMapper`, whereas `JsonLayout.json` template of
+  `JsonTemplateLayout` employs the `StackTraceElementLayout.json` template
   for stack traces to generate a document-store-friendly flat structure.)
 
 Below is the list of supported event template resolvers:
 
 [#event-template-resolvers]
-.<code>LogEvent</code> template resolvers
+.`LogEvent` template resolvers
 [cols="1m,3,2,2,4"]
 |===
 | Resolver Name
@@ -413,7 +413,7 @@ Below is the list of supported event template resolvers:
 
 | endOfBatch
 |
-| <code>logEvent.isEndOfBatch()</code>
+| `logEvent.isEndOfBatch()`
 | none
 a|
 [source,json]
@@ -435,14 +435,14 @@ field       = "field" -> (
 stringified = "stringified" -> boolean
 ----
 a|
-Resolves fields of the <code>Throwable</code> returned by <code>logEvent.getThrown()</code>.
+Resolves fields of the `Throwable` returned by `logEvent.getThrown()`.
 
 Note that this resolver is toggled by
-<code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property.
-| Since <code>Throwable#getStackTrace()</code> clones the original <code>StackTraceElement[]</code>,
+`log4j.layout.jsonTemplate.stackTraceEnabled` property.
+| Since `Throwable#getStackTrace()` clones the original `StackTraceElement[]`,
   access to (and hence rendering of) stack traces are not garbage-free.
 a|
-Resolve <code>logEvent.getThrown().getClass().getCanonicalName()</code>:
+Resolve `logEvent.getThrown().getClass().getCanonicalName()`:
 
 [source,json]
 ----
@@ -452,7 +452,7 @@ Resolve <code>logEvent.getThrown().getClass().getCanonicalName()</code>:
 }
 ----
 
-Resolve the stack trace into a list of <code>StackTraceElement</code> objects:
+Resolve the stack trace into a list of `StackTraceElement` objects:
 
 [source,json]
 ----
@@ -474,15 +474,15 @@ Resolve the stack trace into a string field:
 ----
 
 | exceptionRootCause
-| identical to <code>exception</code> resolver
+| identical to `exception` resolver
 a|
-Resolves the fields of the innermost <code>Throwable</code> returned by
-<code>logEvent.getThrown()</code>.
+Resolves the fields of the innermost `Throwable` returned by
+`logEvent.getThrown()`.
 
 Note that this resolver is toggled by
-<code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property.
-| identical to <code>exception</code> resolver
-| identical to <code>exception</code> resolver
+`log4j.layout.jsonTemplate.stackTraceEnabled` property.
+| identical to `exception` resolver
+| identical to `exception` resolver
 
 | level
 a|
@@ -493,7 +493,7 @@ field          = "field" -> ( "name" \| "severity" )
 severity       = severity-field
 severity-field = "field" -> ( "keyword" \| "code" )
 ----
-| resolves the fields of the <code>logEvent.getLevel()</code>
+| resolves the fields of the `logEvent.getLevel()`
 | none
 a|
 Resolve the level name:
@@ -540,7 +540,7 @@ a|
 ----
 config = "field" -> ( "name" \| "fqcn" )
 ----
-| resolves <code>logEvent.getLoggerFqcn()</code> and <code>logEvent.getLoggerName()</code>
+| resolves `logEvent.getLoggerFqcn()` and `logEvent.getLoggerName()`
 | none
 a|
 Resolve the logger name:
@@ -563,7 +563,7 @@ Resolve the logger's fully qualified class name:
 }
 ----
 
-| main:<key>
+| main
 a|
 [source]
 ----
@@ -572,10 +572,10 @@ index  = "index" -> number
 key    = "key" -> string
 ----
 | performs link:lookups.html#AppMainArgsLookup[Main Argument Lookup] for the
-  given <code>index</code> or <code>key</code>
+  given `index` or `key`
 | none
 a|
-Resolve the 1st <code>main()</code> method argument:
+Resolve the 1st `main()` method argument:
 
 [source,json]
 ----
@@ -585,7 +585,7 @@ Resolve the 1st <code>main()</code> method argument:
 }
 ----
 
-Resolve the argument coming right after <code>--userId</code>:
+Resolve the argument coming right after `--userId`:
 
 [source,json]
 ----
@@ -603,11 +603,11 @@ config      = key , [ stringified ]
 key         = "key" -> string
 stringified = "stringified" -> boolean
 ----
-| resolves the given <code>key</code> of <code>MapMessage</code>s
-| <code>stringified</code> flag translates to <code>String.valueOf(value)</code>, hence mind
-  not-<code>String</code>-typed values.
+| resolves the given `key` of ``MapMessage``s
+| `stringified` flag translates to `String.valueOf(value)`, hence mind
+  not-`String`-typed values.
 a|
-Resolve the <code>userRole</code> field of the message:
+Resolve the `userRole` field of the message:
 
 [source,json]
 ----
@@ -623,7 +623,7 @@ a|
 ----
 config = "field" -> "name"
 ----
-| <code>logEvent.getMarker().getName()</code>
+| `logEvent.getMarker().getName()`
 | none
 a|
 Resolve the marker name:
@@ -654,25 +654,25 @@ flattenPrefix = "prefix" -> string
 ----
 a| Mapped Diagnostic Context (MDC), aka. Thread Context Data, resolver.
 
-<code>singleAccess</code> resolves the MDC value as is, whilst <code>multiAccess</code> resolves a
-multitude of MDC values. If <code>flatten</code> is provided, <code>multiAccess</code> merges the
+`singleAccess` resolves the MDC value as is, whilst `multiAccess` resolves a
+multitude of MDC values. If `flatten` is provided, `multiAccess` merges the
 values with the parent, otherwise creates a new JSON object containing the
 values.
 
-Enabling <code>stringified</code> flag converts each value to its string representation.
+Enabling `stringified` flag converts each value to its string representation.
 
-Regex provided in the <code>pattern</code> is used to match against the keys.
+Regex provided in the `pattern` is used to match against the keys.
 a|
-<code>log4j2.garbagefreeThreadContextMap</code> flag needs to be turned on to iterate
+`log4j2.garbagefreeThreadContextMap` flag needs to be turned on to iterate
 the map without allocations.
 
-<code>stringified</code> allocates a new <code>String</code> for values that are not of type <code>String</code>.
+`stringified` allocates a new `String` for values that are not of type `String`.
 
-Writing certain non-primitive values (e.g., <code>BigDecimal</code>, <code>Set</code>, etc.) to JSON
-generates garbage, though most (e.g., <code>int</code>, <code>long</code>, <code>String</code>, <code>List</code>,
-<code>boolean[]</code>, etc.) don't.
+Writing certain non-primitive values (e.g., `BigDecimal`, `Set`, etc.) to JSON
+generates garbage, though most (e.g., `int`, `long`, `String`, `List`,
+`boolean[]`, etc.) don't.
 a|
-Resolve the <code>userRole</code> MDC value:
+Resolve the `userRole` MDC value:
 
 [source,json]
 ----
@@ -682,7 +682,7 @@ Resolve the <code>userRole</code> MDC value:
 }
 ----
 
-Resolve the string representation of the <code>userRank</code> MDC value:
+Resolve the string representation of the `userRank` MDC value:
 
 [source,json]
 ----
@@ -712,7 +712,7 @@ Resolve all MDC entries into an object such that values are converted to string:
 }
 ----
 
-Merge all MDC entries whose keys are matching with the <code>user(Role\|Rank)</code> regex
+Merge all MDC entries whose keys are matching with the `user(Role\|Rank)` regex
 into the parent:
 
 [source,json]
@@ -725,7 +725,7 @@ into the parent:
 ----
 
 After converting the corresponding entries to string, merge all MDC entries to
-parent such that keys are prefixed with <code>_</code>:
+parent such that keys are prefixed with `_`:
 
 [source,json]
 ----
@@ -748,9 +748,9 @@ includeStackTrace = "includeStacktrae" -> boolean
 stringified = "stringified" -> boolean
 fallbackKey = "fallbackKey" -> string
 ----
-a| <code>logEvent.getMessage()</code>
+a| `logEvent.getMessage()`
 | For simple string messages, the resolution is performed without allocations.
-  For <code>ObjectMessage</code>s and <code>MultiformatMessage</code>s, it depends.
+  For ``ObjectMessage``s and ``MultiformatMessage``s, it depends.
 a|
 Resolve the message into a string:
 
@@ -762,6 +762,17 @@ Resolve the message into a string:
 }
 ----
 
+Resolve the message into a string using a pattern:
+
+[source,json]
+----
+{
+  "$resolver": "message",
+  "pattern": ""[%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m"",
+  "stringified": true
+}
+----
+
 Resolve the message such that if it is an `ObjectMessage` or a
 `MultiformatMessage` with JSON support, its type (string, list, object, etc.)
 will be retained:
@@ -773,12 +784,12 @@ will be retained:
 }
 ----
 
-Given the above configuration, a <code>SimpleMessage</code> will generate a <code>"sample log
-message"</code>, whereas a <code>MapMessage</code> will generate a <code>{"action": "login",
-"sessionId": "87asd97a"}</code>. Certain indexed log storage systems (e.g.,
+Given the above configuration, a `SimpleMessage` will generate a `"sample log
+message"`, whereas a `MapMessage` will generate a `{"action": "login",
+"sessionId": "87asd97a"}`. Certain indexed log storage systems (e.g.,
 https://www.elastic.co/elasticsearch/[Elasticsearch]) will not allow both values
-to coexist due to type mismatch: one is a <code>string</code> while the other is an <code>object</code>.
-Here one can use a <code>fallbackKey</code> to work around the problem:
+to coexist due to type mismatch: one is a `string` while the other is an `object`.
+Here one can use a `fallbackKey` to work around the problem:
 
 [source,json]
 ----
@@ -788,10 +799,10 @@ Here one can use a <code>fallbackKey</code> to work around the problem:
 }
 ----
 
-Using this configuration, a <code>SimpleMessage</code> will generate a
-<code>{"formattedMessage": "sample log message"}</code> and a <code>MapMessage</code> will generate a
-<code>{"action": "login", "sessionId": "87asd97a"}</code>. Note that both emitted JSONs are
-of type <code>object</code> and have no type-conflicting fields.
+Using this configuration, a `SimpleMessage` will generate a
+`{"formattedMessage": "sample log message"}` and a `MapMessage` will generate a
+`{"action": "login", "sessionId": "87asd97a"}`. Note that both emitted JSONs are
+of type `object` and have no type-conflicting fields.
 
 | ndc
 a|
@@ -801,7 +812,7 @@ config  = [ pattern ]
 pattern = "pattern" -> string
 ----
 | Resolves the Nested Diagnostic Context (NDC), aka. Thread Context Stack,
-  <code>String[]</code> returned by <code>logEvent.getContextStack()</code>
+  `String[]` returned by `logEvent.getContextStack()`
 | none
 a|
 Resolve all NDC values into a list:
@@ -813,7 +824,7 @@ Resolve all NDC values into a list:
 }
 ----
 
-Resolve all NDC values matching with the <code>pattern</code> regex:
+Resolve all NDC values matching with the `pattern` regex:
 
 [source,json]
 ----
@@ -832,13 +843,13 @@ pattern           = "pattern" -> string
 stackTraceEnabled = "stackTraceEnabled" -> boolean
 ----
 a|
-Resolver delegating to link:layouts.html#PatternLayout[<code>PatternLayout</code>].
+Resolver delegating to link:layouts.html#PatternLayout[`PatternLayout`].
 
-The default value of <code>stackTraceEnabled</code> is inherited from the parent
-<code>JsonTemplateLayout</code>.
+The default value of `stackTraceEnabled` is inherited from the parent
+`JsonTemplateLayout`.
 | none
 a|
-Resolve the string produced by <code>%p %c{1.} [%t] %X{userId} %X %m%ex</code> pattern:
+Resolve the string produced by `%p %c{1.} [%t] %X{userId} %X %m%ex` pattern:
 
 [source,json]
 ----
@@ -859,11 +870,11 @@ config = "field" -> (
            "lineNumber" )
 ----
 a|
-Resolves the fields of the <code>StackTraceElement</code> returned by
-<code>logEvent.getSource()</code>.
+Resolves the fields of the `StackTraceElement` returned by
+`logEvent.getSource()`.
 
 Note that this resolver is toggled by
-<code>log4j.layout.jsonTemplate.locationInfoEnabled</code> property.
+`log4j.layout.jsonTemplate.locationInfoEnabled` property.
 | none
 a|
 Resolve the line number:
@@ -882,8 +893,8 @@ a|
 ----
 config = "field" -> ( "name" \| "id" \| "priority" )
 ----
-| resolves <code>logEvent.getThreadId()</code>, <code>logEvent.getThreadName()</code>,
-  <code>logEvent.getThreadPriority()</code>
+| resolves `logEvent.getThreadId()`, `logEvent.getThreadName()`,
+  `logEvent.getThreadPriority()`
 | none
 a|
 Resolve the thread name:
@@ -924,10 +935,10 @@ unit          = "unit" -> (
                 )
 rounded       = "rounded" -> boolean
 ----
-| resolves <code>logEvent.getInstant()</code> in various forms
+| resolves `logEvent.getInstant()` in various forms
 | none
 a|
-.<code>timestamp</code> template resolver examples
+.`timestamp` template resolver examples
 [cols="5,2m"]
 !===
 ! Configuration
@@ -1047,11 +1058,11 @@ a!
 [#stack-trace-element-templates]
 === Stack Trace Element Templates
 
-<code>stackTraceElement[Uri]</code> describes the JSON structure <code>JsonTemplateLayout</code> uses
-to format <code>StackTraceElement</code>s. The default configuration (accessible by
-<code>log4j.layout.jsonTemplate.stackTraceElementTemplate[Uri]</code> property) is set to
-<code>classpath:StackTraceElementLayout.json</code> provided by the
-<code>log4j-layout-json-template</code> artifact:
+`stackTraceElement[Uri]` describes the JSON structure `JsonTemplateLayout` uses
+to format ``StackTraceElement``s. The default configuration (accessible by
+`log4j.layout.jsonTemplate.stackTraceElementTemplate[Uri]` property) is set to
+`classpath:StackTraceElementLayout.json` provided by the
+`log4j-layout-json-template` artifact:
 
 [source,json]
 ----
@@ -1086,22 +1097,22 @@ config = "field" -> (
            "lineNumber" )
 ----
 
-All above accesses to <code>StackTraceElement</code> is garbage-free.
+All above accesses to `StackTraceElement` is garbage-free.
 
 [#features]
 == Features
 
-Below is a feature comparison matrix between <code>JsonTemplateLayout</code> and
+Below is a feature comparison matrix between `JsonTemplateLayout` and
 alternatives.
 
 .Feature comparison matrix
 [cols="3,1,1,1,1"]
 |===
 | Feature
-| <code>JsonTemplateLayout</code>
-| link:layouts.html#JSONLayout[<code>JsonLayout</code>]
-| link:layouts.html#GELFLayout[<code>GelfLayout</code>]
-| https://github.com/elastic/java-ecs-logging/tree/master/log4j2-ecs-layout[<code>EcsLayout</code>]
+| `JsonTemplateLayout`
+| link:layouts.html#JSONLayout[`JsonLayout`]
+| link:layouts.html#GELFLayout[`GelfLayout`]
+| https://github.com/elastic/java-ecs-logging/tree/master/log4j2-ecs-layout[`EcsLayout`]
 
 | Java version
 | 8
@@ -1115,7 +1126,7 @@ alternatives.
 | None
 | None
 
-| Full schema customization?
+| Schema customization?
 | ✓
 | ✕
 | ✕
@@ -1133,13 +1144,13 @@ alternatives.
 | ✓
 | ✓
 
-| Custom typed <code>Message</code> serialization?
+| Custom typed `Message` serialization?
 | ✓
 | ✕
 | ✕
-| ?footnote:[Only for <code>ObjectMessage</code>s and if Jackson is in the classpath.]
+| ?footnote:[Only for ``ObjectMessage``s and if Jackson is in the classpath.]
 
-| Custom typed <code>MDC</code> value serialization?
+| Custom typed `MDC` value serialization?
 | ✓
 | ✕
 | ✕
@@ -1157,7 +1168,7 @@ alternatives.
 | ✕
 | ✕
 
-| Additional fields?
+| Additional field support?
 | ✓
 | ✓
 | ✓
@@ -1170,29 +1181,28 @@ alternatives.
 [#faq-lookups]
 === Are lookups supported in templates?
 
-Yes, link:lookups.html[lookups] (e.g., <code>${java:version}</code>, <code>${env:USER}</code>,
-<code>${date:MM-dd-yyyy}</code>) are supported in string literals of templates. Though note
-that they are not garbage-free.
+Yes, link:lookups.html[lookups] (e.g., `${dollar}{java:version}`,
+`${dollar}{env:USER}`, `${dollar}{date:MM-dd-yyyy}`) are supported in string
+literals of templates. Though note that they are not garbage-free.
 
 [#faq-garbage-free]
-=== Is <code>JsonTemplateLayout</code> garbage-free?
+=== Is `JsonTemplateLayout` garbage-free?
 
 Yes, if the garbage-free layout behaviour toggling properties
-<code>log4j2.enableDirectEncoders</code> and <code>log4j2.garbagefreeThreadContextMap</code> are
+`log4j2.enableDirectEncoders` and `log4j2.garbagefreeThreadContextMap` are
 enabled. Take into account the following caveats:
 
 * The configured link:#recycling-strategy[recycling strategy] might not be
   garbage-free.
 
-* Since <code>Throwable#getStackTrace()</code> clones the original <code>StackTraceElement[]</code>,
+* Since `Throwable#getStackTrace()` clones the original `StackTraceElement[]`,
   access to (and hence rendering of) stack traces are not garbage-free.
 
-* Serialization of <code>MapMessage</code>s and <code>ObjectMessage</code>s are mostly
-  garbage-free except for certain types (e.g., <code>BigDecimal</code>, <code>BigInteger</code>,
-  <code>Collection</code>s with the exception of <code>List</code>).
+* Serialization of ``MapMessage``s and ``ObjectMessage``s are mostly
+  garbage-free except for certain types (e.g., `BigDecimal`, `BigInteger`,
+  ``Collection``s with the exception of `List`).
 
-* link:lookups.html[Lookups] (that is, <code>${...}</code> variables, excluding
-  <code>${json:...}</code> ones) are not garbage-free.
+* link:lookups.html[Lookups] (that is, `${...}` variables) are not garbage-free.
 
 Don't forget to checkout link:#event-template-resolvers[the notes on garbage footprint of resolvers]
 you employ in templates.
diff --git a/src/site/xdoc/manual/json-template-layout.xml.vm b/src/site/xdoc/manual/json-template-layout.xml.vm
deleted file mode 100644
index be05a1c..0000000
--- a/src/site/xdoc/manual/json-template-layout.xml.vm
+++ /dev/null
@@ -1,1526 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-
-  <properties>
-    <title>JSON Template Layout</title>
-    <author email="vy@apache.org">Volkan Yazıcı</author>
-  </properties>
-
-  <body>
-
-    <section name="JSON Template Layout">
-
-      <p>
-        <code>JsonTemplateLayout</code> is a customizable, efficient, and
-        garbage-free JSON emitting layout. It encodes <code>LogEvent</code>s
-        according to the structure described by the JSON template provided. In a
-        nutshell, it shines with its
-      </p>
-
-      <ul>
-        <li>
-          Customizable JSON structure (see <code>eventTemplate[Uri]</code> and
-          <code>stackTraceElementTemplate[Uri]</code> parameters)
-        </li>
-        <li>
-          Customizable timestamp formatting (see <code>timestamp</code> parameter)
-        </li>
-      </ul>
-
-      <subsection name="Usage">
-
-        <a name="usage"/>
-
-        <p>
-          Adding <code>log4j-layout-json-template</code> artifact to your list
-          of dependencies is enough to enable access to
-          <code>JsonTemplateLayout</code> in your Log4j configuration:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-<dependency>
-    <groupId>org.apache.logging.log4j</groupId>
-    <artifactId>log4j-layout-json-template</artifactId>
-    <version>${Log4jReleaseVersion}</version>
-</dependency>]]></pre>
-
-        <p>
-          For instance, given the following JSON template modelling the
-          <a href="https://github.com/logstash/log4j-jsonevent-layout">the
-            official Logstash <code>JSONEventLayoutV1</code></a> (accessible via
-          <code>classpath:LogstashJsonEventLayoutV1.json</code>)
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-{
-  "mdc": {
-    "$resolver": "mdc"
-  },
-  "exception": {
-    "exception_class": {
-      "$resolver": "exception",
-      "field": "className"
-    },
-    "exception_message": {
-      "$resolver": "exception",
-      "field": "message",
-      "stringified": true
-    },
-    "stacktrace": {
-      "$resolver": "exception",
-      "field": "stackTrace",
-      "stringified": true
-    }
-  },
-  "line_number": {
-    "$resolver": "source",
-    "field": "lineNumber"
-  },
-  "class": {
-    "$resolver": "source",
-    "field": "className"
-  },
-  "@version": 1,
-  "source_host": "${hostName}",
-  "message": {
-    "$resolver": "message",
-    "stringified": true
-  },
-  "thread_name": {
-    "$resolver": "thread",
-    "field": "name"
-  },
-  "@timestamp": {
-    "$resolver": "timestamp"
-  },
-  "level": {
-    "$resolver": "level",
-    "field": "name"
-  },
-  "file": {
-    "$resolver": "source",
-    "field": "fileName"
-  },
-  "method": {
-    "$resolver": "source",
-    "field": "methodName"
-  },
-  "logger_name": {
-    "$resolver": "logger",
-    "field": "name"
-  }
-}]]></pre>
-
-        <p>
-          in combination with the below <code>log4j2.xml</code> configuration:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/>]]></pre>
-
-        <p>
-          or with the below <code>log4j2.properties</code> configuration:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-appender.console.json.type = JsonTemplateLayout
-appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.json]]></pre>
-
-        <p>
-          <code>JsonTemplateLayout</code> emits JSON strings as follows:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-{
-  "exception": {
-    "exception_class": "java.lang.RuntimeException",
-    "exception_message": "test",
-    "stacktrace": "java.lang.RuntimeException: test\n\tat org.apache.logging.log4j.JsonTemplateLayoutDemo.main(JsonTemplateLayoutDemo.java:11)\n"
-  },
-  "line_number": 12,
-  "class": "org.apache.logging.log4j.JsonTemplateLayoutDemo",
-  "@version": 1,
-  "source_host": "varlik",
-  "message": "Hello, error!",
-  "thread_name": "main",
-  "@timestamp": "2017-05-25T19:56:23.370+02:00",
-  "level": "ERROR",
-  "file": "JsonTemplateLayoutDemo.java",
-  "method": "main",
-  "logger_name": "org.apache.logging.log4j.JsonTemplateLayoutDemo"
-}]]></pre>
-
-      </subsection>
-
-      <subsection name="Layout Configuration">
-
-        <a name="layout-config"/>
-
-        <p>
-          <code>JsonTemplateLayout</code> is configured with the following
-          parameters:
-        </p>
-
-        <table>
-
-          <caption align="top"><code>JsonTemplateLayout</code> parameters</caption>
-
-          <thead>
-            <tr>
-              <th>Parameter Name</th>
-              <th>Type</th>
-              <th>Description</th>
-            </tr>
-          </thead>
-
-          <tbody>
-
-            <tr>
-              <td>charset</td>
-              <td>Charset</td>
-              <td><code>Charset</code> used for <code>String</code> encoding</td>
-            </tr>
-
-            <tr>
-              <td>locationInfoEnabled</td>
-              <td>boolean</td>
-              <td>
-                toggles access to the <code>LogEvent</code> source; file name,
-                line number, etc. (defaults to <code>false</code> set by
-                <code>log4j.layout.jsonTemplate.locationInfoEnabled</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>stackTraceEnabled</td>
-              <td>boolean</td>
-              <td>
-                toggles access to the stack traces (defaults to
-                <code>true</code> set by
-                <code>log4j.layout.jsonTemplate.stackTraceEnabled</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>eventTemplate</td>
-              <td>String</td>
-              <td>
-                inline JSON template for rendering <code>LogEvent</code>s (has
-                priority over <code>eventTemplateUri</code>, defaults to
-                <code>null</code> set by
-                <code>log4j.layout.jsonTemplate.eventTemplate</code> property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>eventTemplateUri</td>
-              <td>String</td>
-              <td>
-                URI pointing to the JSON template for rendering
-                <code>LogEvent</code>s (defaults to
-                <code>classpath:EcsLayout.json</code> set by
-                <code>log4j.layout.jsonTemplate.eventTemplateUri</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>eventTemplateAdditionalFields</td>
-              <td>EventTemplateAdditionalField[]</td>
-              <td>
-                additional key-value pairs appended to the root of the event
-                template
-              </td>
-            </tr>
-
-            <tr>
-              <td>stackTraceElementTemplate</td>
-              <td>String</td>
-              <td>
-                inline JSON template for rendering <code>StackTraceElement</code>s
-                (has priority over <code>stackTraceElementTemplateUri</code>,
-                defaults to <code>null</code> set by
-                <code>log4j.layout.jsonTemplate.stackTraceElementTemplate</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>stackTraceElementTemplateUri</td>
-              <td>String</td>
-              <td>
-                JSON template for rendering <code>StackTraceElement</code>s
-                (defaults to <code>classpath:StackTraceElementLayout.json</code>
-                set by
-                <code>log4j.layout.jsonTemplate.stackTraceElementTemplateUri</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>eventDelimiter</td>
-              <td>String</td>
-              <td>
-                delimiter used for separating emitted <code>LogEvent</code>s
-                (defaults to <code>System.lineSeparator()</code> set by
-                <code>log4j.layout.jsonTemplate.eventDelimiter</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>nullEventDelimiterEnabled</td>
-              <td>boolean</td>
-              <td>
-                append <code>\0</code> (<code>null</code>) character to the end
-                of every emitted <code>eventDelimiter</code> (defaults to
-                <code>false</code> set by
-                <code>log4j.layout.jsonTemplate.nullEventDelimiterEnabled</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>maxStringLength</td>
-              <td>int</td>
-              <td>
-                truncate string values longer than the specified limit (defaults
-                to 16384 set by <code>log4j.layout.jsonTemplate.maxStringLength</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>truncatedStringSuffix</td>
-              <td>String</td>
-              <td>
-                suffix to append to strings truncated due to exceeding
-                <code>maxStringLength</code> (defaults to <code>…</code> set by
-                <code>log4j.layout.jsonTemplate.truncatedStringSuffix</code>
-                property)
-              </td>
-            </tr>
-
-            <tr>
-              <td>recyclerFactory</td>
-              <td>RecyclerFactory</td>
-              <td>
-                recycling strategy that can either be <code>dummy</code>,
-                <code>threadLocal</code>, or <code>queue</code> (set by
-                <code>log4j.layout.jsonTemplate.recyclerFactory</code> property)
-              </td>
-            </tr>
-
-          </tbody>
-
-        </table>
-
-        <h4>Additonal event template fields</h4>
-
-        <a name="additional-event-template-fields"/>
-
-        <p>
-          Additional event template field is a convenient short-cut to add
-          custom fields to a template or override the fields of a template.
-          Following configuration overrides the <code>host</code> field of the
-          <code>GelfLayout.json</code> template and adds two new custom fields:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-<JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json">
-    <EventTemplateAdditionalFields>
-        <EventTemplateAdditionalField key="host" value="www.apache.org"/>
-        <EventTemplateAdditionalField key="_serviceName" value="auth-service"/>
-        <EventTemplateAdditionalField key="_containerId" value="6ede3f0ca7d9"/>
-    </EventTemplateAdditionalFields>
-</JsonTemplateLayout>]]></pre>
-
-        <p>
-          One can also pass JSON literals into additional fields:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[<EventTemplateAdditionalField
-     key="marker"
-     type="JSON"
-     value='{"$resolver": "marker", "field": "name"}'/>
-<EventTemplateAdditionalField
-     key="aNumber"
-     type="JSON"
-     value="1"/>
-<EventTemplateAdditionalField
-     key="aList"
-     type="JSON"
-     value='[1,2,"string"]'/>]]></pre>
-
-        <h4>Recycling strategy</h4>
-
-        <a name="recycling-strategy"/>
-
-        <p>
-          <code>RecyclerFactory</code> plays a crucial role for determining the
-          memory footprint of the layout. Template resolvers employ it to create
-          recyclers for objects that they can reuse. The function of each
-          <code>RecyclerFactory</code> and when one should prefer one over
-          another is explained below:
-        </p>
-
-        <ul>
-
-          <li>
-            <code>dummy</code> performs no recycling, hence each recycling
-            attempt will result in a new instance. This will obviously create a
-            load on the garbage-collector. It is a good choice for applications
-            with low and medium log rate.
-          </li>
-
-          <li>
-            <code>threadLocal</code> performs the best, since every instance is
-            stored in <code>ThreadLocal</code>s and accessed without any
-            synchronization cost. Though this might not be a desirable option
-            for applications running with hundreds of threads or more, e.g., a
-            web servlet.
-          </li>
-
-          <li>
-
-            <p>
-              <code>queue</code> is the best of both worlds. It allows recycling
-              of objects up to a certain number (<code>capacity</code>). When
-              this limit is exceeded due to excessive concurrent load (e.g.,
-              <code>capacity</code> is 50 but there are 51 threads concurrently
-              trying to log), it starts allocating. <code>queue</code> is a good
-              strategy where <code>threadLocal</code> is not desirable.
-            </p>
-
-            <p>
-              <code>queue</code> also accepts optional <code>supplier</code> (of
-              type <code>java.util.Queue</code>, defaults to
-              <code>org.jctools.queues.MpmcArrayQueue.new</code> if JCTools is
-              in the classpath; otherwise
-              <code>java.util.concurrent.ArrayBlockingQueue.new</code>) and
-              <code>capacity</code> (of type <code>int</code>, defaults to
-              <code>max(8,2*cpuCount+1)</code>) parameters:
-            </p>
-
-            <pre class="prettyprint linenums"><![CDATA[
-queue:supplier=org.jctools.queues.MpmcArrayQueue.new
-queue:capacity=10
-queue:supplier=java.util.concurrent.ArrayBlockingQueue.new,capacity=50]]></pre>
-
-            <p>
-              The default <code>RecyclerFactory</code> is
-              <code>threadLocal</code>, if
-              <code>log4j2.enable.threadlocals=true</code>; otherwise,
-              <code>queue</code>.
-            </p>
-
-          </li>
-
-        </ul>
-
-      </subsection>
-
-      <subsection name="Template Configuration">
-
-        <a name="template-config"/>
-
-        <p>
-          Templates are configured by means of the following
-          <code>JsonTemplateLayout</code> parameters:
-        </p>
-
-        <ul>
-          <li>
-            <code>eventTemplate[Uri]</code> (for serializing
-            <code>LogEvent</code>s)
-          </li>
-          <li>
-            <code>stackTraceElementTemplate[Uri]</code> (for serializing
-            <code>StackStraceElement</code>s)
-          </li>
-          <li>
-            <code>eventTemplateAdditionalFields</code> (for extending the used
-            event template)
-          </li>
-        </ul>
-
-        <h4>Event Templates</h4>
-
-        <a name="event-templates"/>
-
-        <p>
-          <code>eventTemplate[Uri]</code> describes the JSON structure
-          <code>JsonTemplateLayout</code> uses to serialize
-          <code>LogEvent</code>s. The default configuration (accessible by
-          <code>log4j.layout.jsonTemplate.eventTemplate[Uri]</code> property) is
-          set to <code>classpath:EcsLayout.json</code> provided by the
-          <code>log4j-layout-json-template</code> artifact:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-{
-  "@timestamp": {
-    "$resolver": "timestamp",
-    "pattern": {
-      "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
-      "timeZone": "UTC"
-    }
-  },
-  "log.level": {
-    "$resolver": "level",
-    "field": "name"
-  },
-  "message": {
-    "$resolver": "message",
-    "stringified": true
-  },
-  "process.thread.name": {
-    "$resolver": "thread",
-    "field": "name"
-  },
-  "log.logger": {
-    "$resolver": "logger",
-    "field": "name"
-  },
-  "labels": {
-    "$resolver": "mdc",
-    "flatten": true,
-    "stringified": true
-  },
-  "tags": {
-    "$resolver": "ndc"
-  },
-  "error.type": {
-    "$resolver": "exception",
-    "field": "className"
-  },
-  "error.message": {
-    "$resolver": "exception",
-    "field": "message"
-  },
-  "error.stack_trace": {
-    "$resolver": "exception",
-    "field": "stackTrace",
-    "stringified": true
-  }
-}]]></pre>
-
-        <p>
-          <code>log4j-layout-json-template</code> artifact contains the
-          following predefined event templates:
-        </p>
-
-        <ul>
-          <li>
-            <a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/EcsLayout.json"><code>EcsLayout.json</code></a>
-            described by <a href="https://www.elastic.co/guide/en/ecs/current/ecs-reference.html">the
-            Elastic Common Schema (ECS) specification</a>
-          </li>
-          <li>
-            <a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/LogstashJsonEventLayoutV1.json"><code>LogstashJsonEventLayoutV1.json</code></a>
-            described in <a href="https://github.com/logstash/log4j-jsonevent-layout">Logstash
-            <code>json_event</code> pattern for log4j</a>
-          </li>
-          <li>
-            <a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/GelfLayout.json"><code>GelfLayout.json</code></a>
-            described by <a href="https://docs.graylog.org/en/3.1/pages/gelf.html#gelf-payload-specification">the
-            Graylog Extended Log Format (GELF) payload specification</a> with
-            additional <code>_thread</code> and <code>_logger</code> fields.
-            (Here it is advised to override the obligatory <code>host</code>
-            field with a user provided constant via <code>eventTemplateAdditionalFields</code>
-            to avoid <code>hostName</code> property lookup at runtime, which
-            incurs an extra cost.)
-          </li>
-          <li>
-            <a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-json-template/src/main/resources/JsonLayout.json"><code>JsonLayout.json</code></a>
-            providing the exact JSON structure generated by
-            <a href="layouts.html#JSONLayout"><code>JsonLayout</code></a> with
-            the exception of <code>thrown</code> field. (<code>JsonLayout</code>
-            serializes the <code>Throwable</code> as is via Jackson
-            <code>ObjectMapper</code>, whereas <code>JsonLayout.json</code>
-            template of <code>JsonTemplateLayout</code> employs the
-            <code>StackTraceElementLayout.json</code> template for stack traces
-            to generate a document-store-friendly flat structure.)
-          </li>
-        </ul>
-
-        <p>
-          Below is the list of supported event template resolvers:
-        </p>
-
-        <a name="event-template-resolvers"/>
-
-        <table>
-
-          <caption align="top"><code>LogEvent</code> template resolvers</caption>
-
-          <thead>
-            <tr>
-              <th width="10%">Resolver Name</th>
-              <th width="30%">Syntax</th>
-              <th width="15%">Description</th>
-              <th width="15%">Garbage Footprint</th>
-              <th width="30%">Examples</th>
-            </tr>
-          </thead>
-
-          <tbody>
-
-            <tr>
-              <td>endOfBatch</td>
-              <td/>
-              <td><code>`logEvent.isEndOfBatch()`</code></td>
-              <td>none</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "endOfBatch"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>exception</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config      = field , [ stringified ]
-field       = "field" -> (
-                "className"  |
-                "message"    |
-                "stackTrace" )
-stringified = "stringified" -> boolean]]></pre>
-              </td>
-              <td>
-                <p>
-                  Resolves fields of the <code>Throwable</code> returned by
-                  <code>logEvent.getThrown()</code>.
-                </p>
-                <p>
-                  Note that this resolver is toggled by
-                  <code>log4j.layout.jsonTemplate.stackTraceEnabled</code>
-                  property.
-                </p>
-              </td>
-              <td>
-                Since <code>Throwable#getStackTrace()</code> clones the original
-                <code>StackTraceElement[]</code>, access to (and hence rendering
-                of) stack traces are not garbage-free.
-              </td>
-              <td>
-                <p>
-                  Resolve <code>logEvent.getThrown().getClass().getCanonicalName()</code>:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "exception",
-  "field": "className"
-}]]></pre>
-                <p>
-                  Resolve the stack trace into a list of
-                  <code>StackTraceElement</code> objects:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "exception",
-  "field": "stackTrace"
-}]]></pre>
-                <p>Resolve the stack trace into a string field:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "exception",
-  "field": "stackTrace",
-  "stringified": true
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>exceptionRootCause</td>
-              <td>identical to <code>exception</code> resolver</td>
-              <td>
-                <p>
-                  Resolves the fields of the innermost <code>Throwable</code>
-                  returned by <code>logEvent.getThrown()</code>.
-                </p>
-                <p>
-                  Note that this resolver is toggled by
-                  <code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property.
-                </p>
-              </td>
-              <td>identical to <code>exception</code> resolver</td>
-              <td>identical to <code>exception</code> resolver</td>
-            </tr>
-
-            <tr>
-              <td>endOfBatch</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config         = field , [ severity ]
-field          = "field" -> ( "name" | "severity" )
-severity       = severity-field
-severity-field = "field" -> ( "keyword" | "code" )]]></pre>
-              </td>
-              <td>resolves the fields of the <code>logEvent.getLevel()</code></td>
-              <td>none</td>
-              <td>
-                <p>Resolve the level name:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "level",
-  "field": "name"
-}]]></pre>
-                <p>
-                  Resolve the
-                  <a href="https://en.wikipedia.org/wiki/Syslog#Severity_levels">Syslog
-                    severity</a> keyword:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "level",
-  "field": "severity",
-  "severity": {
-    "field": "keyword"
-  }
-}]]></pre>
-                <p>
-                  Resolve the
-                  <a href="https://en.wikipedia.org/wiki/Syslog#Severity_levels">Syslog
-                    severity</a> code:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "level",
-  "field": "severity",
-  "severity": {
-    "field": "code"
-  }
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>logger</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config = "field" -> ( "name" | "fqcn" )]]></pre>
-              </td>
-              <td>
-                resolves <code>logEvent.getLoggerFqcn()</code> and
-                <code>logEvent.getLoggerName()</code>
-              </td>
-              <td>none</td>
-              <td>
-                <p>Resolve the logger name:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "logger",
-  "field": "name"
-}]]></pre>
-                <p>Resolve the logger's fully qualified class name:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "logger",
-  "field": "fqcn"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>main</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config = ( index | key )
-index  = "index" -> number
-key    = "key" -> string]]></pre>
-              </td>
-              <td>
-                performs <a href="lookups.html#AppMainArgsLookup">Main Argument
-                Lookup</a> for the given <code>index</code> or <code>key</code>
-              </td>
-              <td>none</td>
-              <td>
-                <p>
-                  Resolve the 1<sup>st</sup> <code>main()</code> method
-                  argument:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "main",
-  "index": 0
-}]]></pre>
-                <p>
-                  Resolve the argument coming right after <code>--userId</code>:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "main",
-  "key": "--userId"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>map</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config      = key , [ stringified ]
-key         = "key" -> string
-stringified = "stringified" -> boolean]]></pre>
-              </td>
-              <td>
-                resolves the given <code>key</code> of <code>MapMessage</code>s
-              </td>
-              <td>
-                <code>stringified</code> flag translates to
-                <code>String.valueOf(value)</code>, hence mind
-                not-<code>String</code>-typed values.
-              </td>
-              <td>
-                <p>Resolve the <code>userRole</code> field of the message:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "map",
-  "key": "userRole"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>marker</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config = "field" -> "name"]]></pre>
-              </td>
-              <td><code>logEvent.getMarker().getName()</code></td>
-              <td>none</td>
-              <td>
-                <p>Resolve the marker name:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "marker",
-  "field": "name"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>mdc</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config        = singleAccess | multiAccess
-
-singleAccess  = key , [ stringified ]
-key           = "key" -> string
-stringified   = "stringified" -> boolean
-
-multi-access  = [ pattern ] , [ flatten ] , [ stringified ]
-pattern       = "pattern" -> string
-flatten       = "flatten" -> ( boolean | flattenConfig )
-flattenConfig = [ flattenPrefix ]
-flattenPrefix = "prefix" -> string]]></pre>
-              </td>
-              <td>
-                <p>
-                  Mapped Diagnostic Context (MDC), aka. Thread Context Data,
-                  resolver.
-                </p>
-                <p>
-                  <code>singleAccess</code> resolves the MDC value as is, whilst
-                  <code>multiAccess</code> resolves a multitude of MDC values.
-                  If <code>flatten</code> is provided, <code>multiAccess</code>
-                  merges the values with the parent, otherwise creates a new
-                  JSON object containing the values.
-                </p>
-                <p>
-                  Enabling <code>stringified</code> flag converts each value to
-                  its string representation.
-                </p>
-                <p>
-                  Regex provided in the <code>pattern</code> is used to match
-                  against the keys.
-                </p>
-              </td>
-              <td>
-                <p>
-                  <code>log4j2.garbagefreeThreadContextMap</code> flag needs to
-                  be turned on to iterate the map without allocations.
-                </p>
-                <p>
-                  <code>stringified</code> allocates a new <code>String</code>
-                  for values that are not of type <code>String</code>.
-                </p>
-                <p>
-                  Writing certain non-primitive values (e.g.,
-                  <code>BigDecimal</code>, <code>Set</code>, etc.) to JSON
-                  generates garbage, though most (e.g., <code>int</code>,
-                  <code>long</code>, <code>String</code>, <code>List</code>,
-                  <code>boolean[]</code>, etc.) don't.
-                </p>
-              </td>
-              <td>
-                <p>Resolve the <code>userRole</code> MDC value:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc",
-  "key": "userRole"
-}]]></pre>
-                <p>
-                  Resolve the string representation of the <code>userRank</code>
-                  MDC value:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc",
-  "key": "userRank",
-  "stringified": true
-}]]></pre>
-                <p>Resolve all MDC entries into an object:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc"
-}]]></pre>
-                <p>
-                  Resolve all MDC entries into an object such that values are
-                  converted to string:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc",
-  "stringified": true
-}]]></pre>
-                <p>
-                  Merge all MDC entries whose keys are matching with the
-                  <code>user(Role|Rank)</code> regex into the parent:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc",
-  "flatten": true,
-  "pattern": "user(Role|Rank)"
-}]]></pre>
-                <p>
-                  After converting the corresponding entries to string, merge
-                  all MDC entries to parent such that keys are prefixed with
-                  <code>_</code>:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "mdc",
-  "stringified": true,
-  "flatten": {
-    "prefix": "_"
-  }
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>message</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config      = [ stringified ] , [ fallbackKey ]
-pattern = "pattern" -> string
-includeStackTrace = "includeStacktrae" -> boolean
-stringified = "stringified" -> boolean
-fallbackKey = "fallbackKey" -> string]]></pre>
-              </td>
-              <td><code>logEvent.getMessage()</code></td>
-              <td>
-                For simple string messages, the resolution is performed without
-                allocations. For <code>ObjectMessage</code>s and
-                <code>MultiformatMessage</code>s, it depends.
-              </td>
-              <td>
-                <p>Resolve the message into a string:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "message",
-  "stringified": true
-}]]></pre>
-                <p>Resolve the message into a string using a pattern:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "message",
-  "stringified": true
-}]]></pre>
-                <p>
-                  Resolve the message such that if it is an
-                  <code>ObjectMessage</code> or a
-                  <code>MultiformatMessage</code> with JSON support, its type
-                  (string, list, object, etc.) will be retained:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "message"
-}]]></pre>
-                <p>
-                  Given the above configuration, a <code>SimpleMessage</code>
-                  will generate a <code>"sample log message"</code>, whereas a
-                  <code>MapMessage</code> will generate a <code>{"action": "login",
-                  "sessionId": "87asd97a"}</code>. Certain indexed log storage
-                  systems (e.g.,
-                  <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a>)
-                  will not allow both values to coexist due to type mismatch:
-                  one is a <code>string</code> while the other is an
-                  <code>object</code>. Here one can use a
-                  <code>fallbackKey</code> to work around the problem:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "message",
-  "fallbackKey": "formattedMessage"
-}]]></pre>
-                <p>
-                  Using this configuration, a <code>SimpleMessage</code> will
-                  generate a <code>{"formattedMessage": "sample log message"}</code>
-                  and a <code>MapMessage</code> will generate a
-                  <code>{"action": "login", "sessionId": "87asd97a"}</code>.
-                  Note that both emitted JSONs are of type <code>object</code>
-                  and have no type-conflicting fields.
-                </p>
-              </td>
-            </tr>
-
-            <tr>
-              <td>ndc</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config  = [ pattern ]
-pattern = "pattern" -> string]]></pre>
-              </td>
-              <td>
-                Resolves the Nested Diagnostic Context (NDC), aka. Thread
-                Context Stack, <code>String[]</code> returned by
-                <code>logEvent.getContextStack()</code>
-              </td>
-              <td>none</td>
-              <td>
-                <p>Resolve all NDC values into a list:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "ndc"
-}]]></pre>
-                <p>
-                  Resolve all NDC values matching with the <code>pattern</code>
-                  regex:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "ndc",
-  "pattern": "user(Role|Rank):\w+"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>pattern</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config            = pattern , [ stackTraceEnabled ]
-pattern           = "pattern" -> string
-stackTraceEnabled = "stackTraceEnabled" -> boolean]]></pre>
-              </td>
-              <td>
-                <p>
-                  Resolver delegating to
-                  <a href="layouts.html#PatternLayout"><code>PatternLayout</code></a>.
-                </p>
-                <p>
-                  The default value of <code>stackTraceEnabled</code> is
-                  inherited from the parent <code>JsonTemplateLayout</code>.
-                </p>
-              </td>
-              <td>none</td>
-              <td>
-                <p>
-                  Resolve the string produced by <code>%p %c{1.} [%t] %X{userId}
-                  %X %m%ex</code> pattern:
-                </p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "pattern",
-  "pattern": "%p %c{1.} [%t] %X{userId} %X %m%ex"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>source</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config = "field" -> (
-           "className"  |
-           "fileName"   |
-           "methodName" |
-           "lineNumber" )]]></pre>
-              </td>
-              <td>
-                <p>
-                  Resolves the fields of the <code>StackTraceElement</code>
-                  returned by <code>logEvent.getSource()</code>.
-                </p>
-                <p>
-                  Note that this resolver is toggled by
-                  <code>log4j.layout.jsonTemplate.locationInfoEnabled</code>
-                  property.
-                </p>
-              </td>
-              <td>none</td>
-              <td>
-                <p>Resolve the line number:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "source",
-  "field": "lineNumber"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>thread</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config = "field" -> ( "name" | "id" | "priority" )]]></pre>
-              </td>
-              <td>
-                resolves <code>logEvent.getThreadId()</code>,
-                <code>logEvent.getThreadName()</code>,
-                <code>logEvent.getThreadPriority()</code>
-              </td>
-              <td>none</td>
-              <td>
-                <p>Resolve the thread name:</p>
-                <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "thread",
-  "field": "name"
-}]]></pre>
-              </td>
-            </tr>
-
-            <tr>
-              <td>timestamp</td>
-              <td>
-                <pre class="prettyprint linenums"><![CDATA[
-config        = [ patternConfig | epochConfig ]
-
-patternConfig = "pattern" -> (
-                  [ format ]   ,
-                  [ timeZone ] ,
-                  [ locale ]   )
-format        = "format" -> string
-timeZone      = "timeZone" -> string
-locale        = "locale" -> (
-                   language                                   |
-                 ( language , "_" , country )                 |
-                 ( language , "_" , country , "_" , variant )
-               )
-
-epochConfig   = "epoch" -> ( unit , [ rounded ] )
-unit          = "unit" -> (
-                   "nanos"         |
-                   "millis"        |
-                   "secs"          |
-                   "millis.nanos"  |
-                   "secs.nanos"    |
-                )
-rounded       = "rounded" -> boolean]]></pre>
-              </td>
-              <td>
-                resolves <code>logEvent.getInstant()</code> in various forms
-              </td>
-              <td>none</td>
-              <td>
-                <table>
-
-                  <caption align="top">
-                    <code>timestamp</code> template resolver examples
-                  </caption>
-
-                  <thead>
-                    <tr>
-                      <th>Configuration</th>
-                      <th>Output</th>
-                    </tr>
-                  </thead>
-
-                  <tbody>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp"
-}]]></pre>
-                      </td>
-                      <td>2020-02-07T13:38:47.098+02:00</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "pattern": {
-    "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
-    "timeZone": "UTC",
-    "locale": "en_US"
-  }
-}]]></pre>
-                      </td>
-                      <td>2020-02-07T13:38:47.098Z</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "secs"
-  }
-}]]></pre>
-                      </td>
-                      <td>1581082727.982123456</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "secs",
-    "rounded": true
-  }
-}]]></pre>
-                      </td>
-                      <td>1581082727</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "secs.nanos"
-  }
-}]]></pre>
-                      </td>
-                      <td>982123456</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "millis"
-  }
-}]]></pre>
-                      </td>
-                      <td>1581082727982.123456</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "millis",
-    "rounded": true
-  }
-}]]></pre>
-                      </td>
-                      <td>1581082727982</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "millis.nanos"
-  }
-}]]></pre>
-                      </td>
-                      <td>123456</td>
-                    </tr>
-
-                    <tr>
-                      <td>
-                        <pre class="prettyprint linenums"><![CDATA[
-{
-  "$resolver": "timestamp",
-  "epoch": {
-    "unit": "nanos"
-  }
-}]]></pre>
-                      </td>
-                      <td>1581082727982123456</td>
-                    </tr>
-
-                  </tbody>
-
-                </table>
-              </td>
-            </tr>
-
-          </tbody>
-
-        </table>
-
-        <h4>Stack Trace Element Templates</h4>
-
-        <a name="stack-trace-element-templates"/>
-
-        <p>
-          <code>stackTraceElement[Uri]</code> describes the JSON structure
-          <code>JsonTemplateLayout</code> uses to format
-          <code>StackTraceElement</code>s. The default configuration (accessible
-          by <code>log4j.layout.jsonTemplate.stackTraceElementTemplate[Uri]</code>
-          property) is set to <code>classpath:StackTraceElementLayout.json</code>
-          provided by the <code>log4j-layout-json-template</code> artifact:
-        </p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-{
-  "class": {
-    "$resolver": "stackTraceElement",
-    "field": "className"
-  },
-  "method": {
-    "$resolver": "stackTraceElement",
-    "field": "methodName"
-  },
-  "file": {
-    "$resolver": "stackTraceElement",
-    "field": "fileName"
-  },
-  "line": {
-    "$resolver": "stackTraceElement",
-    "field": "lineNumber"
-  }
-}]]></pre>
-
-        <p>The allowed template configuration syntax is as follows:</p>
-
-        <pre class="prettyprint linenums"><![CDATA[
-config = "field" -> (
-           "className"  |
-           "fileName"   |
-           "methodName" |
-           "lineNumber" )]]></pre>
-
-      </subsection>
-
-      <p>
-        All above accesses to <code>StackTraceElement</code> is garbage-free.
-      </p>
-
-    </section>
-
-    <section name="Features">
-
-      <a name="features"/>
-
-      <p>
-        Below is a feature comparison matrix between
-        <code>JsonTemplateLayout</code> and alternatives.
-      </p>
-
-      <table>
-
-        <caption align="top">Feature comparison matrix</caption>
-
-        <thead>
-          <tr>
-            <th>Feature</th>
-            <th><code>JsonTemplateLayout</code></th>
-            <th><a href="layouts.html#JSONLayout"><code>JsonLayout</code></a></th>
-            <th><a href="layouts.html#GELFLayout"><code>GelfLayout</code></a></th>
-            <th><a href="https://github.com/elastic/java-ecs-logging/tree/master/log4j2-ecs-layout"><code>EcsLayout</code></a></th>
-          </tr>
-        </thead>
-
-        <tbody>
-
-          <tr>
-            <td>Java version</td>
-            <td>8</td>
-            <td>8</td>
-            <td>8</td>
-            <td>6</td>
-          </tr>
-
-          <tr>
-            <td>Dependencies</td>
-            <td>None</td>
-            <td>Jackson</td>
-            <td>None</td>
-            <td>None</td>
-          </tr>
-
-          <tr>
-            <td>Schema customization?</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✕</td>
-            <td>✕</td>
-          </tr>
-
-          <tr>
-            <td>Timestamp customization?</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✕</td>
-            <td>✕</td>
-          </tr>
-
-          <tr>
-            <td>(Almost) garbage-free?</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✓</td>
-            <td>✓</td>
-          </tr>
-
-          <tr>
-            <td>Custom typed <code>Message</code> serialization?</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✕</td>
-            <td>?<sup>1</sup></td>
-          </tr>
-
-          <tr>
-            <td>Custom typed <code>MDC</code> value serialization?</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✕</td>
-            <td>✕</td>
-          </tr>
-
-          <tr>
-            <td>Rendering stack traces as array?</td>
-            <td>✓</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✓</td>
-          </tr>
-
-          <tr>
-            <td>JSON pretty print?</td>
-            <td>✕</td>
-            <td>✓</td>
-            <td>✕</td>
-            <td>✕</td>
-          </tr>
-
-          <tr>
-            <td>Additional field support?</td>
-            <td>✓</td>
-            <td>✓</td>
-            <td>✓</td>
-            <td>✓</td>
-          </tr>
-
-        </tbody>
-
-      </table>
-
-      <p>
-        <sup>1</sup> Only for <code>ObjectMessage</code>s and if Jackson is in
-        the classpath.
-      </p>
-
-    </section>
-
-    <section name="F.A.Q">
-
-      <a name="faq"/>
-
-      <h4>Are lookups supported in templates?</h4>
-
-      <a name="faq-lookups"/>
-
-      <p>
-        Yes, <a href="lookups.html">lookups</a> (e.g.,
-        <code>&#36;{java:version}</code>, <code>&#36;{env:USER}</code>,
-        <code>&#36;{date:MM-dd-yyyy}</code>) are supported in string
-        literals of templates. Though note that they are not garbage-free.
-      </p>
-
-      <h4>Is <code>JsonTemplateLayout</code> garbage-free?</h4>
-
-      <a name="faq-garbage-free"/>
-
-      <p>
-        Yes, if the garbage-free layout behaviour toggling properties
-        <code>log4j2.enableDirectEncoders</code> and
-        <code>log4j2.garbagefreeThreadContextMap</code> are enabled. Take into
-        account the following caveats:
-      </p>
-
-      <ul>
-
-        <li>
-          The configured <a href="#recycling-strategy">recycling strategy</a>
-          might not be garbage-free.
-        </li>
-
-        <li>
-          Since <code>Throwable#getStackTrace()</code> clones the original
-          <code>StackTraceElement[]</code>, access to (and hence rendering of)
-          stack traces are not garbage-free.
-        </li>
-
-        <li>
-          Serialization of <code>MapMessage</code>s and
-          <code>ObjectMessage</code>s are mostly garbage-free except for certain
-          types (e.g., <code>BigDecimal</code>, <code>BigInteger</code>,
-          <code>Collection</code>s with the exception of <code>List</code>).
-        </li>
-
-        <li>
-          <a href="lookups.html">Lookups</a> (that is, <code>${...}</code>
-          variables) are not garbage-free.
-        </li>
-
-      </ul>
-
-      <p>
-        Don't forget to checkout <a href="#event-template-resolvers">the notes
-        on garbage footprint of resolvers</a> you employ in templates.
-      </p>
-
-    </section>
-
-  </body>
-
-</document>