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

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


The following commit(s) were added to refs/heads/main by this push:
     new 406eba9a6f Support parents in `MarkerResolver` (#1381)
406eba9a6f is described below

commit 406eba9a6f7780d6c3094540723f11936a955bc3
Author: Eric Herot <[email protected]>
AuthorDate: Tue Mar 21 17:05:41 2023 -0400

    Support parents in `MarkerResolver` (#1381)
---
 .../log4j/layout/template/json/TestHelpers.java    |  9 ++-
 .../template/json/resolver/MarkerResolverTest.java | 94 ++++++++++++++++++++++
 .../template/json/resolver/MarkerResolver.java     | 41 +++++++++-
 .../asciidoc/manual/json-template-layout.adoc.vm   | 54 +++++++++++++
 4 files changed, 194 insertions(+), 4 deletions(-)

diff --git 
a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
index 07f3234060..6a8a4a90e9 100644
--- 
a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
+++ 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
@@ -75,14 +75,17 @@ public final class TestHelpers {
             final Consumer<MapAccessor> accessorConsumer) {
         final String serializedLogEventJson = layout.toSerializable(logEvent);
         @SuppressWarnings("unchecked")
-        final Map<String, Object> deserializedLogEvent =
-                (Map<String, Object>) readJson(serializedLogEventJson);
+        final Map<String, Object> deserializedLogEvent = (Map<String, Object>) 
readJson(serializedLogEventJson);
         final MapAccessor serializedLogEventAccessor = new 
MapAccessor(deserializedLogEvent);
         accessorConsumer.accept(serializedLogEventAccessor);
     }
 
     public static Object readJson(final String json) {
-        return JsonReader.read(json);
+        try {
+            return JsonReader.read(json);
+        } catch (final Exception error) {
+            throw new RuntimeException("failed to deserialize the JSON: " + 
json, error);
+        }
     }
 
     public static Map<String, Object> asMap(final Object... pairs) {
diff --git 
a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolverTest.java
 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolverTest.java
new file mode 100644
index 0000000000..8eeb6f7f4a
--- /dev/null
+++ 
b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolverTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.layout.template.json.resolver;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+class MarkerResolverTest {
+
+    @Test
+    void should_have_a_marker_name() {
+
+        // Create the event template
+        final String eventTemplate = writeJson(asMap(
+                "marker", asMap(
+                        "$resolver", "marker",
+                        "field", "name")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create the log event.
+        final Marker marker = MarkerManager.getMarker("MARKER");
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMarker(marker)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor ->
+                assertThat(accessor.getString("marker")).isEqualTo("MARKER"));
+
+    }
+
+    @Test
+    void should_list_parents_as_array() {
+
+        // Create the event template
+        final String eventTemplate = writeJson(asMap(
+                "parents", asMap(
+                        "$resolver", "marker",
+                        "field", "parents")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create the log event.
+        final Marker parentMarker1 = 
MarkerManager.getMarker("PARENT_MARKER_NAME_1");
+        final Marker parentMarker2 = 
MarkerManager.getMarker("PARENT_MARKER_NAME_2");
+        final Marker childMarker = 
MarkerManager.getMarker("CHILD_MARKER_NAME");
+        childMarker.setParents(parentMarker1, parentMarker2);
+
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMarker(childMarker)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor ->
+                assertThat(accessor.getList("parents", String.class))
+                        .containsOnly(parentMarker1.getName(), 
parentMarker2.getName()));
+
+    }
+
+}
diff --git 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolver.java
 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolver.java
index fc1c30c9bc..4975fd2a15 100644
--- 
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolver.java
+++ 
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MarkerResolver.java
@@ -26,7 +26,7 @@ import 
org.apache.logging.log4j.layout.template.json.util.JsonWriter;
  * <h3>Configuration</h3>
  *
  * <pre>
- * config = "field" -> "name"
+ * config = "field" -> ( "name" | "parents" )
  * </pre>
  *
  * <h3>Examples</h3>
@@ -39,6 +39,15 @@ import 
org.apache.logging.log4j.layout.template.json.util.JsonWriter;
  *   "field": "name"
  * }
  * </pre>
+ *
+ * Resolve the names of the marker's parents:
+ *
+ * <pre>
+ * {
+ *   "$resolver": "marker",
+ *   "field": "parents"
+ * }
+ * </pre>
  */
 public final class MarkerResolver implements EventResolver {
 
@@ -52,6 +61,30 @@ public final class MarkerResolver implements EventResolver {
                 }
             };
 
+    private static final TemplateResolver<LogEvent> PARENTS_RESOLVER =
+            (final LogEvent logEvent, final JsonWriter jsonWriter) -> {
+
+                // Short-circuit if there are no parents
+                final Marker marker = logEvent.getMarker();
+                if (marker == null || !marker.hasParents()) {
+                    jsonWriter.writeNull();
+                    return;
+                }
+
+                // Write parents
+                final Marker[] parents = marker.getParents();
+                jsonWriter.writeArrayStart();
+                for (int parentIndex = 0; parentIndex < parents.length; 
parentIndex++) {
+                    if (parentIndex > 0) {
+                        jsonWriter.writeSeparator();
+                    }
+                    final Marker parentMarker = parents[parentIndex];
+                    jsonWriter.writeString(parentMarker.getName());
+                }
+                jsonWriter.writeArrayEnd();
+
+            };
+
     private final TemplateResolver<LogEvent> internalResolver;
 
     MarkerResolver(final TemplateResolverConfig config) {
@@ -61,9 +94,15 @@ public final class MarkerResolver implements EventResolver {
     private TemplateResolver<LogEvent> createInternalResolver(
             final TemplateResolverConfig config) {
         final String fieldName = config.getString("field");
+
         if ("name".equals(fieldName)) {
             return NAME_RESOLVER;
         }
+
+        if ("parents".equals(fieldName)) {
+            return PARENTS_RESOLVER;
+        }
+
         throw new IllegalArgumentException("unknown field: " + config);
     }
 
diff --git a/src/site/asciidoc/manual/json-template-layout.adoc.vm 
b/src/site/asciidoc/manual/json-template-layout.adoc.vm
index f1bb103a21..ad61105033 100644
--- a/src/site/asciidoc/manual/json-template-layout.adoc.vm
+++ b/src/site/asciidoc/manual/json-template-layout.adoc.vm
@@ -743,6 +743,8 @@ Each `pointMatcherRegexes` item triggers a 
`Pattern#matcher()` call, which is
 not garbage-free either.
 ====
 
+====== Examples
+
 Resolve `logEvent.getThrown().getClass().getCanonicalName()`:
 
 [source,json]
@@ -849,6 +851,8 @@ severity-field = "field" -> ( "keyword" | "code" )
 
 Resolves the fields of the `logEvent.getLevel()`.
 
+====== Examples
+
 Resolve the level name:
 
 [source,json]
@@ -897,6 +901,8 @@ config = "field" -> ( "name" | "fqcn" )
 
 Resolves `logEvent.getLoggerFqcn()` and `logEvent.getLoggerName()`.
 
+====== Examples
+
 Resolve the logger name:
 
 [source,json]
@@ -930,6 +936,8 @@ key    = "key" -> string
 Performs link:lookups.html#AppMainArgsLookup[Main Argument Lookup] for the
 given `index` or `key`.
 
+====== Examples
+
 Resolve the 1st `main()` method argument:
 
 [source,json]
@@ -956,6 +964,38 @@ Resolve the argument coming right after `--userId`:
 Resolves ``MapMessage``s. See link:#map-resolver-template[Map Resolver 
Template]
 for details.
 
+[#event-template-resolver-marker]
+===== `marker`
+
+[source]
+----
+config = "field" -> ( "name" | "parents" )
+----
+
+Resolves `logEvent.getMarker()`.
+
+====== Examples
+
+Resolve the marker name:
+
+[source,json]
+----
+{
+  "$resolver": "marker",
+  "field": "name"
+}
+----
+
+Resolve the names of the marker's parents:
+
+[source,json]
+----
+{
+  "$resolver": "marker",
+  "field": "parents"
+}
+----
+
 [#event-template-resolver-mdc]
 ===== `mdc`
 
@@ -986,6 +1026,8 @@ For simple string messages, the resolution is performed 
without allocations.
 For ``ObjectMessage``s and ``MultiformatMessage``s, it depends.
 ====
 
+====== Examples
+
 Resolve the message into a string:
 
 [source,json]
@@ -1047,6 +1089,8 @@ Regarding garbage footprint, `stringified` flag 
translates to
 which is the case if `log4j2.enableThreadLocals` property set to true.
 ====
 
+====== Examples
+
 Resolve the message parameters into an array:
 
 [source,json]
@@ -1099,6 +1143,8 @@ pattern = "pattern" -> string
 Resolves the Nested Diagnostic Context (NDC), aka. Thread Context Stack,
 `String[]` returned by `logEvent.getContextStack()`.
 
+====== Examples
+
 Resolve all NDC values into a list:
 
 [source,json]
@@ -1133,6 +1179,8 @@ Resolver delegating to 
link:layouts.html#PatternLayout[`PatternLayout`].
 The default value of `stackTraceEnabled` is inherited from the parent
 `JsonTemplateLayout`.
 
+====== Examples
+
 Resolve the string produced by `%p %c{1.} [%t] %X{userId} %X %m%ex` pattern:
 
 [source,json]
@@ -1161,6 +1209,8 @@ Resolves the fields of the `StackTraceElement` returned by
 Note that this resolver is toggled by
 `log4j.layout.jsonTemplate.locationInfoEnabled` property.
 
+====== Examples
+
 Resolve the line number:
 
 [source,json]
@@ -1182,6 +1232,8 @@ config = "field" -> ( "name" | "id" | "priority" )
 Resolves `logEvent.getThreadId()`, `logEvent.getThreadName()`,
 `logEvent.getThreadPriority()`.
 
+====== Examples
+
 Resolve the thread name:
 
 [source,json]
@@ -1221,6 +1273,8 @@ rounded       = "rounded" -> boolean
 
 Resolves `logEvent.getInstant()` in various forms.
 
+====== Examples
+
 .`timestamp` template resolver examples
 [cols="5,2m"]
 |===

Reply via email to