diff --git a/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/TraceResolverTest.java b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/TraceResolverTest.java new file mode 100644 index 00000000000..0de00e22d82 --- /dev/null +++ b/log4j-layout-template-json-test/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/TraceResolverTest.java @@ -0,0 +1,87 @@ +/* + * 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 static org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION; +import static org.apache.logging.log4j.layout.template.json.TestHelpers.asMap; +import static org.apache.logging.log4j.layout.template.json.TestHelpers.usingSerializedLogEventAccessor; +import static org.apache.logging.log4j.layout.template.json.TestHelpers.writeJson; +import static org.assertj.core.api.Assertions.assertThat; + +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; + +class TraceResolverTest { + + @Test + void should_resolve_trace_metadata() { + + // Create the event template using JTL TestHelpers + final String eventTemplate = writeJson(asMap( + "traceId", asMap("$resolver", "traceId"), + "spanId", asMap("$resolver", "spanId"), + "traceFlags", asMap("$resolver", "traceFlags"))); + + // Create the layout + final JsonTemplateLayout layout = JsonTemplateLayout.newBuilder() + .setConfiguration(CONFIGURATION) + .setEventTemplate(eventTemplate) + .build(); + + // Create the log event with active tracing data + final LogEvent logEvent = Log4jLogEvent.newBuilder() + .setTraceId("4bf92f3577b34da6a3ce929d0e0e4736") + .setSpanId("00f067aa0ba902b7") + .setTraceFlags("01") + .build(); + + // Check the serialized event parses the JSON correctly + usingSerializedLogEventAccessor(layout, logEvent, accessor -> { + assertThat(accessor.getString("traceId")).isEqualTo("4bf92f3577b34da6a3ce929d0e0e4736"); + assertThat(accessor.getString("spanId")).isEqualTo("00f067aa0ba902b7"); + assertThat(accessor.getString("traceFlags")).isEqualTo("01"); + }); + } + + @Test + void should_resolve_empty_metadata_safely() { + + // Create the event template + final String eventTemplate = writeJson(asMap( + "traceId", asMap("$resolver", "traceId"), + "spanId", asMap("$resolver", "spanId"), + "traceFlags", asMap("$resolver", "traceFlags"))); + + // Create the layout + final JsonTemplateLayout layout = JsonTemplateLayout.newBuilder() + .setConfiguration(CONFIGURATION) + .setEventTemplate(eventTemplate) + .build(); + + // Create the log event with NO tracing data (simulating default behavior) + final LogEvent logEvent = Log4jLogEvent.newBuilder().build(); + + // Check the serialized event does not throw exceptions and handles missing fields safely + usingSerializedLogEventAccessor(layout, logEvent, accessor -> { + assertThat(accessor.getString("traceId")).isNullOrEmpty(); + assertThat(accessor.getString("spanId")).isNullOrEmpty(); + assertThat(accessor.getString("traceFlags")).isNullOrEmpty(); + }); + } +} diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/package-info.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/package-info.java index ab2e6c5b08d..e60735571b5 100644 --- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/package-info.java +++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/package-info.java @@ -16,7 +16,7 @@ */ @Export @Open("org.apache.logging.log4j.core") -@Version("2.21.0") +@Version("2.22.0") package org.apache.logging.log4j.layout.template.json; import aQute.bnd.annotation.jpms.Open; diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolver.java new file mode 100644 index 00000000000..4325a447255 --- /dev/null +++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolver.java @@ -0,0 +1,53 @@ +/* + * 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.core.LogEvent; +import org.apache.logging.log4j.layout.template.json.util.JsonWriter; + +/** + * Resolves the W3C standard span ID. + * + *
+ * {
+ * "$resolver": "spanId"
+ * }
+ *
+ */
+public final class SpanIdResolver implements EventResolver {
+
+ private static final SpanIdResolver INSTANCE = new SpanIdResolver();
+
+ SpanIdResolver() {}
+
+ static SpanIdResolver getInstance() {
+ return INSTANCE;
+ }
+
+ static String getName() {
+ return "spanId";
+ }
+
+ @Override
+ public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
+ jsonWriter.writeString(logEvent.getSpanId());
+ }
+}
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolverFactory.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolverFactory.java
new file mode 100644
index 00000000000..520452be527
--- /dev/null
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/SpanIdResolverFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * {@link SpanIdResolver} factory.
+ */
+@Plugin(name = "SpanIdResolverFactory", category = TemplateResolverFactory.CATEGORY)
+public final class SpanIdResolverFactory implements EventResolverFactory {
+
+ private static final SpanIdResolverFactory INSTANCE = new SpanIdResolverFactory();
+
+ private SpanIdResolverFactory() {}
+
+ @PluginFactory
+ public static SpanIdResolverFactory getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public String getName() {
+ return SpanIdResolver.getName();
+ }
+
+ @Override
+ public SpanIdResolver create(final EventResolverContext context, final TemplateResolverConfig config) {
+ return SpanIdResolver.getInstance();
+ }
+}
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolver.java
new file mode 100644
index 00000000000..23d46227d3a
--- /dev/null
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolver.java
@@ -0,0 +1,53 @@
+/*
+ * 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.core.LogEvent;
+import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
+
+/**
+ * Resolves the W3C standard trace flags.
+ *
+ *
+ * {
+ * "$resolver": "traceFlags"
+ * }
+ *
+ */
+public final class TraceFlagsResolver implements EventResolver {
+
+ private static final TraceFlagsResolver INSTANCE = new TraceFlagsResolver();
+
+ TraceFlagsResolver() {}
+
+ static TraceFlagsResolver getInstance() {
+ return INSTANCE;
+ }
+
+ static String getName() {
+ return "traceFlags";
+ }
+
+ @Override
+ public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
+ jsonWriter.writeString(logEvent.getTraceFlags());
+ }
+}
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolverFactory.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolverFactory.java
new file mode 100644
index 00000000000..29955b81d56
--- /dev/null
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceFlagsResolverFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * {@link TraceFlagsResolver} factory.
+ */
+@Plugin(name = "TraceFlagsResolverFactory", category = TemplateResolverFactory.CATEGORY)
+public final class TraceFlagsResolverFactory implements EventResolverFactory {
+
+ private static final TraceFlagsResolverFactory INSTANCE = new TraceFlagsResolverFactory();
+
+ private TraceFlagsResolverFactory() {}
+
+ @PluginFactory
+ public static TraceFlagsResolverFactory getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public String getName() {
+ return TraceFlagsResolver.getName();
+ }
+
+ @Override
+ public TraceFlagsResolver create(final EventResolverContext context, final TemplateResolverConfig config) {
+ return TraceFlagsResolver.getInstance();
+ }
+}
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolver.java
new file mode 100644
index 00000000000..894a253d37d
--- /dev/null
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolver.java
@@ -0,0 +1,53 @@
+/*
+ * 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.core.LogEvent;
+import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
+
+/**
+ * Resolves the W3C standard trace ID.
+ *
+ *
+ * {
+ * "$resolver": "traceId"
+ * }
+ *
+ */
+public final class TraceIdResolver implements EventResolver {
+
+ private static final TraceIdResolver INSTANCE = new TraceIdResolver();
+
+ TraceIdResolver() {}
+
+ static TraceIdResolver getInstance() {
+ return INSTANCE;
+ }
+
+ static String getName() {
+ return "traceId";
+ }
+
+ @Override
+ public void resolve(final LogEvent logEvent, final JsonWriter jsonWriter) {
+ jsonWriter.writeString(logEvent.getTraceId());
+ }
+}
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolverFactory.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolverFactory.java
new file mode 100644
index 00000000000..1ba09517812
--- /dev/null
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TraceIdResolverFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * {@link TraceIdResolver} factory.
+ */
+@Plugin(name = "TraceIdResolverFactory", category = TemplateResolverFactory.CATEGORY)
+public final class TraceIdResolverFactory implements EventResolverFactory {
+
+ private static final TraceIdResolverFactory INSTANCE = new TraceIdResolverFactory();
+
+ private TraceIdResolverFactory() {}
+
+ @PluginFactory
+ public static TraceIdResolverFactory getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public String getName() {
+ return TraceIdResolver.getName();
+ }
+
+ @Override
+ public TraceIdResolver create(final EventResolverContext context, final TemplateResolverConfig config) {
+ return TraceIdResolver.getInstance();
+ }
+}
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 376a67bd335..3b704adbc0b 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.21.0")
+@Version("2.22.0")
package org.apache.logging.log4j.layout.template.json.resolver;
import aQute.bnd.annotation.jpms.Open;
diff --git a/src/changelog/fix_jtl_trace_resolvers.xml b/src/changelog/fix_jtl_trace_resolvers.xml
new file mode 100644
index 00000000000..5d2454b25a6
--- /dev/null
+++ b/src/changelog/fix_jtl_trace_resolvers.xml
@@ -0,0 +1,13 @@
+
+