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

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


The following commit(s) were added to refs/heads/2.x by this push:
     new be863cf901 Improve layout docs on property substitution (#2667)
be863cf901 is described below

commit be863cf901b643e754efee2216d5b13f3ae208f9
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Wed Jun 19 14:46:11 2024 +0200

    Improve layout docs on property substitution (#2667)
---
 .../resources/threadLocalRecyclerNestedLogging.xml |   4 +-
 .../json/resolver/TemplateResolverContext.java     |   2 +-
 .../TemplateResolverStringSubstitutor.java         |   4 +-
 .../template/json/resolver/package-info.java       |   2 +-
 .../log4j2.json                                    |   0
 .../log4j2.properties                              |   0
 .../log4j2.xml                                     |   0
 .../log4j2.yaml                                    |   0
 .../property-substitution/log4j2.json              |  27 ++++
 .../log4j2.properties}                             |  34 ++---
 .../log4j2.xml                                     |  17 +--
 .../log4j2.yaml                                    |  14 +-
 .../modules/ROOT/pages/manual/garbagefree.adoc     |   4 +-
 .../ROOT/pages/manual/json-template-layout.adoc    | 155 ++++++++++++++++++---
 .../antora/modules/ROOT/pages/manual/layouts.adoc  |   4 -
 .../antora/modules/ROOT/pages/manual/lookups.adoc  |   1 +
 .../modules/ROOT/pages/manual/pattern-layout.adoc  |  50 ++++++-
 .../partials/manual/layouts-gcfree-lookup.adoc     |  21 ---
 18 files changed, 234 insertions(+), 105 deletions(-)

diff --git 
a/log4j-layout-template-json-test/src/test/resources/threadLocalRecyclerNestedLogging.xml
 
b/log4j-layout-template-json-test/src/test/resources/threadLocalRecyclerNestedLogging.xml
index e3f5be0b8e..06c8a99022 100644
--- 
a/log4j-layout-template-json-test/src/test/resources/threadLocalRecyclerNestedLogging.xml
+++ 
b/log4j-layout-template-json-test/src/test/resources/threadLocalRecyclerNestedLogging.xml
@@ -30,9 +30,7 @@
   <Loggers>
     <Root level="trace">
       <AppenderRef ref="List1"/>
-    </Root>
-    <Logger name="org" level="trace">
       <AppenderRef ref="List2"/>
-    </Logger>
+    </Root>
   </Loggers>
 </Configuration>
diff --git 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverContext.java
 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverContext.java
index 74ca965887..e7522e3da9 100644
--- 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverContext.java
+++ 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverContext.java
@@ -30,7 +30,7 @@ import 
org.apache.logging.log4j.layout.template.json.util.JsonWriter;
  *
  * @see TemplateResolverFactory
  */
-interface TemplateResolverContext<V, C extends TemplateResolverContext<V, C>> {
+public interface TemplateResolverContext<V, C extends 
TemplateResolverContext<V, C>> {
 
     Class<C> getContextClass();
 
diff --git 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverStringSubstitutor.java
 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverStringSubstitutor.java
index 64b54a0202..c765dc8427 100644
--- 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverStringSubstitutor.java
+++ 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverStringSubstitutor.java
@@ -28,8 +28,8 @@ public interface TemplateResolverStringSubstitutor<V> {
     StrSubstitutor getInternalSubstitutor();
 
     /**
-     * A substitutor is stable if the replacement doesn't vary with the 
provided
-     * value. In such a case, value is always set to {@code null}.
+     * A substitutor is stable if the replacement doesn't vary with the 
provided value.
+     * That is, in a stable substitutor, {@code value} argument of {@link 
#replace(Object, String)} is always ignored.
      */
     boolean isStable();
 
diff --git 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/package-info.java
 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/package-info.java
index 6398bdffb3..376a67bd33 100644
--- 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/package-info.java
+++ 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/package-info.java
@@ -16,7 +16,7 @@
  */
 @Export
 @Open("org.apache.logging.log4j.core")
-@Version("2.20.1")
+@Version("2.21.0")
 package org.apache.logging.log4j.layout.template.json.resolver;
 
 import aQute.bnd.annotation.jpms.Open;
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.json
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.json
similarity index 100%
rename from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.json
rename to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.json
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.properties
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.properties
similarity index 100%
rename from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.properties
rename to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.properties
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.xml
similarity index 100%
copy from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml
copy to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.xml
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.yaml
similarity index 100%
copy from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
copy to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/event-template-additional-field/log4j2.yaml
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.json
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.json
new file mode 100644
index 0000000000..bf85540b4d
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.json
@@ -0,0 +1,27 @@
+{
+  "Configuration": {
+    "Appenders": {
+      "Console": {
+        "name": "CONSOLE",
+        "JsonTemplateLayout": {
+          "eventTemplate": "{\"instant\": {\"$resolver\": \"pattern\", 
\"pattern\": \"${env:LOG4J_DATE_PATTERN:-%d}\"}}", //<1>
+          "eventTemplateAdditionalField": [
+            {
+              "key": "message",
+              "format": "JSON",
+              "value": "{\"$resolver\": \"pattern\", \"pattern\": 
\"${env:LOG4J_MESSAGE_PATTERN:-%m}\"}" //<2>
+            }
+          ]
+        }
+      }
+    },
+    "Loggers": {
+      "Root": {
+        "level": "WARN",
+        "AppenderRef": {
+          "ref": "CONSOLE"
+        }
+      }
+    }
+  }
+}
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.properties
similarity index 55%
copy from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
copy to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.properties
index 0349dd2575..d32d6cd88d 100644
--- 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
+++ 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.properties
@@ -14,28 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-Configuration:
+appender.0.type = Console
+appender.0.name = CONSOLE
+appender.0.layout.type = JsonTemplateLayout
+appender.0.layout.eventTemplate = {"instant": {"$resolver": "pattern", 
"pattern": "${env:LOG4J_DATE_PATTERN:-%d}"}} #<1>
+appender.0.layout.eventTemplateAdditionalField[0].type = 
EventTemplateAdditionalField
+appender.0.layout.eventTemplateAdditionalField[0].key = message
+appender.0.layout.eventTemplateAdditionalField[0].format = JSON
+appender.0.layout.eventTemplateAdditionalField[0].value = {"$resolver": 
"pattern", "pattern": "${env:LOG4J_MESSAGE_PATTERN:-%m}"} #<2>
 
-  Appenders:
-    Console:
-      name: "CONSOLE"
-      JsonTemplateLayout:
-        eventTemplateUri: "classpath:GelfLayout.json"
-        eventTemplateAdditionalField:
-          - key: "aString"
-            value: "foo" #<1>
-          - key: "marker"
-            value: '{"$resolver": "marker", "field": "name"}'
-            format: "JSON"
-          - key: "aNumber"
-            value: "1"
-            format: "JSON"
-          - key: "aList"
-            value: '[1, 2, "three"]'
-            format: "JSON"
-
-  Loggers:
-    Root:
-      level: "WARN"
-      AppenderRef:
-        ref: "CONSOLE"
+rootLogger.level = WARN
+rootLogger.appenderRef.0.ref = CONSOLE
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.xml
similarity index 74%
rename from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml
rename to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.xml
index c6b2f32ae8..8e44b6e96c 100644
--- 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml
+++ 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.xml
@@ -23,22 +23,11 @@
 
   <Appenders>
     <Console name="CONSOLE">
-      <JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json">
+      <JsonTemplateLayout eventTemplate='{"instant": {"$resolver": "pattern", 
"pattern": "${env:LOG4J_DATE_PATTERN:-%d}"}}'> <!--1-->
         <EventTemplateAdditionalField
-            key="aString"
-            value="foo"/><!--1-->
-        <EventTemplateAdditionalField
-            key="marker"
-            format="JSON"
-            value='{"$resolver": "marker", "field": "name"}'/>
-        <EventTemplateAdditionalField
-            key="aNumber"
-            format="JSON"
-            value="1"/>
-        <EventTemplateAdditionalField
-            key="aList"
+            key="message"
             format="JSON"
-            value='[1, 2, "three"]'/>
+            value='{"$resolver": "pattern", "pattern": 
"${env:LOG4J_MESSAGE_PATTERN:-%m}"}'/> <!--2-->
       </JsonTemplateLayout>
     </Console>
   </Appenders>
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.yaml
similarity index 73%
rename from 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
rename to 
src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.yaml
index 0349dd2575..382e9e5af4 100644
--- 
a/src/site/antora/modules/ROOT/examples/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml
+++ 
b/src/site/antora/modules/ROOT/examples/manual/json-template-layout/property-substitution/log4j2.yaml
@@ -20,19 +20,11 @@ Configuration:
     Console:
       name: "CONSOLE"
       JsonTemplateLayout:
-        eventTemplateUri: "classpath:GelfLayout.json"
+        eventTemplate: '{"instant": {"$resolver": "pattern", "pattern": 
"${env:LOG4J_DATE_PATTERN:-%d}"}}' #<1>
         eventTemplateAdditionalField:
-          - key: "aString"
-            value: "foo" #<1>
-          - key: "marker"
-            value: '{"$resolver": "marker", "field": "name"}'
-            format: "JSON"
-          - key: "aNumber"
-            value: "1"
-            format: "JSON"
-          - key: "aList"
-            value: '[1, 2, "three"]'
+          - key: "message"
             format: "JSON"
+            value: '{"$resolver": "pattern", "pattern": 
"${env:LOG4J_MESSAGE_PATTERN:-%m}"}' #<2>
 
   Loggers:
     Root:
diff --git a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc 
b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
index c8736c8ef1..5bc6438cfa 100644
--- a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
@@ -57,7 +57,7 @@ If not for yours, keep on reading.
 In order to have a garbage-free Log4j Core, you need to
 
 * <<core-properties,configure it using properties>>,
-* and employ garbage-free <<Layouts[layouts], xref:Appenders[appenders], and 
xref:#Filters,filters>>.
+* and employ garbage-free <<Layouts,layouts>>, <<Appenders,appenders>>, and 
<<Filters,filters>>.
 
 [#core-properties]
 === Properties
@@ -211,7 +211,7 @@ Not all Log4j API feature set is garbage-free, specifically:
 * The `ThreadContext` map (aka. MDC) is not garbage-free by default, but can 
be configured to be garbage-free by setting 
<<log4j2.garbagefreeThreadContextMap,the `log4j2.garbagefreeThreadContextMap` 
system property>> to `true`.
 * The `ThreadContext` stack (aka. NDC) is not garbage-free.
 * xref:manual/scoped-context.adoc[] is not garbage-free.
-* Logging very large messages (i.e., more than 
<<log4j2.maxReusableMsgSize[`log4j2.maxReusableMsgSize`] characters, which 
defaults to 518), when all loggers are xref:manual/async.adoc,asynchronous 
loggers>>, will cause the internal `StringBuilder` in the
+* Logging very large messages (i.e., more than <<log4j2.maxReusableMsgSize>> 
characters, which defaults to 518), when all loggers are 
xref:manual/async.adoc[asynchronous loggers], will cause the internal 
`StringBuilder` in the
 `RingBuffer` to be trimmed back to their configured maximum size.
 * Logging messages containing `$\{variable}` substitutions creates temporary 
objects.
 * Logging a lambda as a parameter:
diff --git 
a/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc 
b/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
index 016450092c..2b36a611dc 100644
--- a/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
@@ -16,7 +16,7 @@
 ////
 = JSON Template Layout
 
-`JsonTemplateLayout` is a customizable, <<performance,efficient>>, and 
xref:#faq-garbage-free,garbage-free>> JSON generating layout.
+`JsonTemplateLayout` is a customizable, <<performance,efficient>>, and 
<<faq-garbage-free,garbage-free>> JSON generating layout.
 It encodes ``LogEvent``s according to the structure described by the JSON 
template provided.
 In a nutshell, it shines with its
 
@@ -348,7 +348,7 @@ That is,
     "key00002": "value00002",
     "key00003": "value00003",
     // ...
-    "key16384": "value16384",
+    "key16384": "value16384"
   }
 }
 ----
@@ -403,34 +403,34 @@ Below we share an example configuration overriding the 
`GelfLayout.json` event t
 ====
 XML::
 +
-.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml[`log4j2.xml`]
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/event-template-additional-field/log4j2.xml[`log4j2.xml`]
 [source,xml]
 ----
-include::example$manual/json-template-layout/eventTemplateAdditionalField/log4j2.xml[lines=26..42,indent=0]
+include::example$manual/json-template-layout/event-template-additional-field/log4j2.xml[lines=26..42,indent=0]
 ----
 
 JSON::
 +
-.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/eventTemplateAdditionalField/log4j2.json[`log4j2.json`]
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/event-template-additional-field/log4j2.json[`log4j2.json`]
 [source,json]
 ----
-include::example$manual/json-template-layout/eventTemplateAdditionalField/log4j2.json[lines=6..29,indent=0]
+include::example$manual/json-template-layout/event-template-additional-field/log4j2.json[lines=6..29,indent=0]
 ----
 
 YAML::
 +
-.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml[`log4j2.yaml`]
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/event-template-additional-field/log4j2.yaml[`log4j2.yaml`]
 [source,xml]
 ----
-include::example$manual/json-template-layout/eventTemplateAdditionalField/log4j2.yaml[lines=22..35,indent=0]
+include::example$manual/json-template-layout/event-template-additional-field/log4j2.yaml[lines=22..35,indent=0]
 ----
 
 Properties::
 +
-.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/eventTemplateAdditionalField/log4j2.properties[`log4j2.properties`]
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/event-template-additional-field/log4j2.properties[`log4j2.properties`]
 [source,xml]
 ----
-include::example$manual/json-template-layout/eventTemplateAdditionalField/log4j2.properties[lines=19..35,indent=0]
+include::example$manual/json-template-layout/event-template-additional-field/log4j2.properties[lines=19..35,indent=0]
 ----
 ====
 <1> Since the `format` attribute is not explicitly set, the default (i.e., 
`STRING`) will be used
@@ -1208,6 +1208,8 @@ pattern           = "pattern" -> string
 stackTraceEnabled = "stackTraceEnabled" -> boolean
 ----
 
+Unlike providing the `pattern` attribute to Pattern Layout in a configuration 
file, <<faq-lookups,property substitutions>> found in the `pattern` will _not_ 
be resolved.
+
 The default value of `stackTraceEnabled` is inherited from the parent JSON 
Template Layout.
 
 [NOTE]
@@ -1642,6 +1644,127 @@ config = "field" -> (
 
 All above accesses to `StackTraceElement` is garbage-free.
 
+[#faq-lookups]
+== Property substitution
+
+Property substitutions (e.g., `$\{myProperty}`), including 
xref:manual/lookups.adoc[lookups] (e.g., `${java:version}`, `${env:USER}`, 
`${date:MM-dd-yyyy}`), are supported, but extra care needs to be taken.
+*We strongly advise you to carefully read 
xref:manual/configuration.adoc#property-substitution[the configuration manual]* 
before using them.
+
+[IMPORTANT]
+====
+xref:manual/lookups.adoc[] are intended as a very generic, convenience utility 
to perform string interpolation for, in particular, configuration files and 
components (e.g., layouts) lacking this mechanism.
+*JSON Template Layout has a rich template resolver collection, and you should 
always prefer it whenever possible over lookups.*
+
+.Which resolvers can I use to replace lookups?
+[%collapsible]
+=====
+[%header,cols="1,1"]
+|===
+|Instead of this lookup
+|Use this resolver
+
+|xref:manual/lookups.adoc#ContextMapLookup[Context Map Lookup]
+|<<event-template-resolver-mdc>>
+
+|xref:manual/lookups.adoc#DateLookup[Date Lookup]
+|<<event-template-resolver-timestamp>>
+
+|xref:manual/lookups.adoc#EventLookup[Event Lookup]
+|<<event-template-resolver-exception>> +
+<<event-template-resolver-level>> +
+<<event-template-resolver-logger>> +
+<<event-template-resolver-marker>> +
+<<event-template-resolver-message>> +
+<<event-template-resolver-thread>> +
+<<event-template-resolver-timestamp>>
+
+|xref:manual/lookups.adoc#LowerLookup[Lower Lookup]
+|<<event-template-resolver-caseConverter>>
+
+|xref:manual/lookups.adoc#AppMainArgsLookup[Main Arguments Lookup]
+|<<event-template-resolver-main>>
+
+|xref:manual/lookups.adoc#MapLookup[Map Lookup]
+|<<event-template-resolver-map>>
+
+|xref:manual/lookups.adoc#marker-lookup[Marker Lookup]
+|<<event-template-resolver-marker>>
+
+|xref:manual/lookups.adoc#UpperLookup[Upper Lookup]
+|<<event-template-resolver-caseConverter>>
+|===
+=====
+====
+
+[#property-substitution-in-template]
+=== Property substitution in event templates
+
+JSON Template Layout performs property substitution in string literals in 
templates, except if they are located in _configuration object of resolvers_.
+Consider the following event template file provided using 
<<plugin-attr-eventTemplateUri,the `eventTemplateUri` attribute>>:
+
+[source,json]
+----
+{
+    "java-version": "${java:version}", //<1>
+    "pid": {
+      "$resolver": "pattern",
+      "pattern": "${env:NO_SUCH_KEY:-%pid}" //<2>
+    }
+}
+----
+<1> This works. `${java:version}` will be replaced with the corresponding 
value.
+<2> This won't work! That is, `${env:NO_SUCH_KEY:-%pid}` literal will not get 
substituted, since it is located in a _configuration object of a resolver_.
+
+[#property-substitution-in-config]
+=== Property substitution in configuration files
+
+If the very same event template <<property-substitution-in-template,shared 
above>> is inlined in a configuration file using 
<<plugin-attr-eventTemplate,the `eventTemplate` attribute>> or 
<<plugin-element-EventTemplateAdditionalField,additional event template 
fields>>, then all substitutions will be replaced, once, at configuration-time.
+This has nothing to do with the JSON Template Layout, but the substitution 
performed by the configuration mechanism when the configuration is read.
+Consider the following example:
+
+[tabs]
+====
+XML::
++
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/property-substitution/log4j2.xml[`log4j2.xml`]
+[source,xml]
+----
+include::example$manual/json-template-layout/property-substitution/log4j2.xml[lines=26..31,indent=0]
+----
+
+JSON::
++
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/property-substitution/log4j2.json[`log4j2.json`]
+[source,json]
+----
+include::example$manual/json-template-layout/property-substitution/log4j2.json[lines=6..15,indent=0]
+----
+
+YAML::
++
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/property-substitution/log4j2.yaml[`log4j2.yaml`]
+[source,xml]
+----
+include::example$manual/json-template-layout/property-substitution/log4j2.yaml[lines=22..27,indent=0]
+----
+
+Properties::
++
+.Snippet from an example 
{antora-examples-url}/manual/json-template-layout/property-substitution/log4j2.properties[`log4j2.properties`]
+[source,xml]
+----
+include::example$manual/json-template-layout/property-substitution/log4j2.properties[lines=19..24,indent=0]
+----
+====
+<1> `eventTemplate` will be passed to the layout with `${env:...}` substituted
+<2> `value` will be passed to the layout with `${env:...}` substituted
+
+[WARNING]
+====
+External values injected this way can corrupt your JSON schema.
+It is your responsibility to ensure the sanitization and safety of the 
substitution source.
+====
+
 [#recycling-strategy]
 == Recycling strategy
 
@@ -2051,13 +2174,6 @@ To get the most out of it, mind the following checklist:
 [#faq]
 == F.A.Q.
 
-[#faq-lookups]
-=== Are lookups supported in templates?
-
-Yes, xref:manual/lookups.adoc[lookups] (e.g., `${java:version}`, 
`${env:USER}`, `${date:MM-dd-yyyy}`) are supported in string literals of 
templates.
-
-include::partial$manual/layouts-gcfree-lookup.adoc[]
-
 [#faq-recursive-collection]
 === Are recursive collections supported?
 
@@ -2085,6 +2201,7 @@ Take into account the following caveats:
 
 * Serialization of ``MapMessage``s and ``ObjectMessage``s are mostly 
garbage-free except for certain types (e.g., `BigDecimal`, `BigInteger`, 
``Collection``s, except `List`).
 
-* xref:manual/lookups.adoc[Lookups] (that is, `${...}` variables) are not 
garbage-free.
+* <<faq-lookups,Property substitutions>> (that is, `${...}` variables) _might_ 
not be garbage-free.
 
-Don't forget to check out <<event-template-resolvers,the notes on garbage 
footprint of resolvers>> you employ in templates.
+<<event-template-resolvers>> contain notes on their garbage footprint.
+Make sure to check those notes of resolvers you employ in templates.
diff --git a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc 
b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
index 457c71c7d8..1551802e5f 100644
--- a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
@@ -631,8 +631,6 @@ runtimeOnly 
'com.fasterxml.jackson.core:jackson-databind:{jackson-version}'
 `JsonTemplateLayout` is a customizable, efficient, and garbage-free JSON 
generating layout.
 It encodes ``LogEvent``s according to the structure described by the JSON 
template provided.
 
-xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-layout-template-json_org-apache-logging-log4j-layout-template-json-JsonTemplateLayout[📖
 Plugin reference for `JsonTemplateLayout`]
-
 For instance, given the following event template stored in `MyLayout.json` in 
your classpath:
 
 [source,json]
@@ -718,8 +716,6 @@ Pattern Layout is not intended for _structural logging_ 
purposes.
 For production environments, you are strongly advised to use 
xref:manual/json-template-layout.adoc[] producing JSON output ready to be 
delivered to log ingestion systems such as Elasticsearch or Google Cloud 
Logging.
 ====
 
-xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-layout-PatternLayout[📖
 Plugin reference for `PatternLayout`]
-
 A conversion pattern is composed of literal text and format control 
expressions.
 For instance, given the `%-5p [%t]: %m%n` pattern, following statements
 
diff --git a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc 
b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index 3b24c6ee4d..b417b5cd9e 100644
--- a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
@@ -469,6 +469,7 @@ page for information on how to set the default values.
 </Routing>
 ----
 
+[#marker-lookup]
 == Marker Lookup
 
 The marker lookup allows you to use markers in interesting
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc 
b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index e8a43cb32c..ab4216480f 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -17,7 +17,7 @@
 
 = Pattern Layout
 
-`PatternLayout` is a customizable, <<performance[efficient], 
xref:#garbage-free,garbage-free>>, and human-readable string generating layout 
using a user-provided pattern.
+`PatternLayout` is a customizable, <<performance,efficient>>, 
<<garbage-free,garbage-free>>, and human-readable string generating layout 
using a user-provided pattern.
 It is analogous to `String#format()` with specialized directives on injecting 
certain properties of a `LogEvent`.
 
 [IMPORTANT]
@@ -1678,12 +1678,56 @@ Format modifiers to control such things as field width, 
padding, left, and right
 |
 
 |literal text
-a|Garbage-free, but care is needed for xref:manual/lookups.adoc[].
-include::partial$manual/layouts-gcfree-lookup.adoc[]
+a|Garbage-free, but care is needed for <<property-substitution>>, including 
xref:manual/lookups.adoc[]
 |===
 
 Patterns containing regular expressions and 
xref:manual/layouts.adoc#LocationInformation[location information] are not 
garbage-free.
 
+[#property-substitution]
+== Property substitution
+
+xref:manual/configuration.adoc#property-substitution[Property substitutions] 
(e.g., `$\{myProperty}`), including xref:manual/lookups.adoc[lookups] (e.g., 
`${java:version}`, `${env:USER}`, `${date:MM-dd-yyyy}`) are supported, but 
extra care needs to be taken.
+*We strongly advise you to carefully read 
xref:manual/configuration.adoc#property-substitution[the configuration manual]* 
before using them.
+
+[IMPORTANT]
+====
+xref:manual/lookups.adoc[] are intended as a very generic, convenience utility 
to perform string interpolation for, in particular, configuration files and 
components (e.g., layouts) lacking this mechanism.
+*Pattern Layout has a rich converter collection, and you should always prefer 
it whenever possible over lookups.*
+
+.Which converters can I use to replace lookups?
+[%collapsible]
+=====
+[%header,cols="1,1"]
+|===
+|Instead of this lookup
+|Use this converter
+
+|xref:manual/lookups.adoc#ContextMapLookup[Context Map Lookup]
+|<<converter-thread-context-map>>
+
+|xref:manual/lookups.adoc#DateLookup[Date Lookup]
+|<<converter-date>>
+
+|xref:manual/lookups.adoc#EventLookup[Event Lookup]
+|<<converter-exception>> +
+<<converter-exception-extended>> +
+<<converter-level>> +
+<<converter-logger>> +
+<<converter-marker>> +
+<<converter-message>> +
+<<converter-thread-id>> +
+<<converter-thread-name>> +
+<<converter-date>>
+
+|xref:manual/lookups.adoc#MapLookup[Map Lookup]
+|<<converter-map>>
+
+|xref:manual/lookups.adoc#marker-lookup[Marker Lookup]
+|<<converter-marker>>
+|===
+=====
+====
+
 [#extending]
 == Extending
 
diff --git 
a/src/site/antora/modules/ROOT/partials/manual/layouts-gcfree-lookup.adoc 
b/src/site/antora/modules/ROOT/partials/manual/layouts-gcfree-lookup.adoc
deleted file mode 100644
index 1fd022a2f5..0000000000
--- a/src/site/antora/modules/ROOT/partials/manual/layouts-gcfree-lookup.adoc
+++ /dev/null
@@ -1,21 +0,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.
-////
-
-Encoding the output of a lookup is garbage-free, but executing the lookup 
might not be.
-For instance, even though xref:manual/lookups.adoc#DateLookup[the `date` 
lookup] allocates a new `String` for each invocation, adding 
`${date:YYYY-MM-dd}` is garbage-free, because it will be expanded at 
configuration time, that is, only once.
-Whereas adding `$${date:YYYY-MM-dd}` is not, since it will be expanded for 
each log event.
-See xref:manual/configuration.adoc#property-substitution[property 
substitution] for details.

Reply via email to