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"]
|===