diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts b/instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts
index 5c315ed3394f..9d616d079f9a 100644
--- a/instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts
+++ b/instrumentation/logback/logback-mdc-1.0/javaagent/build.gradle.kts
@@ -10,6 +10,42 @@ muzzle {
}
}
+testing {
+ suites {
+ val addBaggageTest by registering(JvmTestSuite::class) {
+ targets {
+ all {
+ testTask.configure {
+ jvmArgs("-Dotel.instrumentation.logback-mdc.add-baggage=true")
+ }
+ }
+ }
+ }
+
+ withType(JvmTestSuite::class) {
+ dependencies {
+ if (findProperty("testLatestDeps") as Boolean) {
+ implementation("ch.qos.logback:logback-classic:+")
+ } else {
+ implementation("ch.qos.logback:logback-classic") {
+ version {
+ strictly("1.0.0")
+ }
+ }
+ implementation("org.slf4j:slf4j-api") {
+ version {
+ strictly("1.6.4")
+ }
+ }
+ }
+
+ implementation(project(":instrumentation:logback:logback-mdc-1.0:testing"))
+ implementation(project(":instrumentation:logback:logback-mdc-1.0:javaagent"))
+ }
+ }
+ }
+}
+
dependencies {
implementation(project(":instrumentation:logback:logback-mdc-1.0:library"))
@@ -24,21 +60,10 @@ dependencies {
strictly("1.6.4")
}
}
+}
- if (findProperty("testLatestDeps") as Boolean) {
- testImplementation("ch.qos.logback:logback-classic:+")
- } else {
- testImplementation("ch.qos.logback:logback-classic") {
- version {
- strictly("1.0.0")
- }
- }
- testImplementation("org.slf4j:slf4j-api") {
- version {
- strictly("1.6.4")
- }
- }
+tasks {
+ named("check") {
+ dependsOn(testing.suites)
}
-
- testImplementation(project(":instrumentation:logback:logback-mdc-1.0:testing"))
}
diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/groovy/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackWithBaggageTest.groovy b/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/groovy/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackWithBaggageTest.groovy
new file mode 100644
index 000000000000..e2468e46cc9a
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/groovy/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackWithBaggageTest.groovy
@@ -0,0 +1,12 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.logback.v1_0
+
+import io.opentelemetry.instrumentation.logback.mdc.v1_0.AbstractLogbackWithBaggageTest
+import io.opentelemetry.instrumentation.test.AgentTestTrait
+
+class LogbackWithBaggageTest extends AbstractLogbackWithBaggageTest implements AgentTestTrait {
+}
diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/resources/logback.xml b/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/resources/logback.xml
new file mode 100644
index 000000000000..3434fbaaab59
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/addBaggageTest/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ %coloredLevel %logger{15} - %message%n%xException{10}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java
new file mode 100644
index 000000000000..a14cac81706e
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.logback.mdc.v1_0;
+
+import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
+
+public final class LogbackSingletons {
+ private static final boolean ADD_BAGGAGE =
+ ConfigPropertiesUtil.getBoolean("otel.instrumentation.logback-mdc.add-baggage", false);
+
+ public static boolean addBaggage() {
+ return ADD_BAGGAGE;
+ }
+
+ private LogbackSingletons() {}
+}
diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java
index aeb4ce31bd64..e2f8130e9406 100644
--- a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java
+++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java
@@ -17,6 +17,8 @@
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import ch.qos.logback.classic.spi.ILoggingEvent;
+import io.opentelemetry.api.baggage.Baggage;
+import io.opentelemetry.api.baggage.BaggageEntry;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.util.VirtualField;
@@ -54,11 +56,11 @@ public void transform(TypeTransformer transformer) {
@SuppressWarnings("unused")
public static class GetMdcAdvice {
-
@Advice.OnMethodExit(suppress = Throwable.class)
public static void onExit(
@Advice.This ILoggingEvent event,
@Advice.Return(typing = Typing.DYNAMIC, readOnly = false) Map contextData) {
+
if (contextData != null && contextData.containsKey(TRACE_ID)) {
// Assume already instrumented event if traceId is present.
return;
@@ -69,15 +71,28 @@ public static void onExit(
return;
}
+ Map spanContextData = new HashMap<>();
+
SpanContext spanContext = Java8BytecodeBridge.spanFromContext(context).getSpanContext();
- if (!spanContext.isValid()) {
- return;
+
+ if (spanContext.isValid()) {
+ spanContextData.put(TRACE_ID, spanContext.getTraceId());
+ spanContextData.put(SPAN_ID, spanContext.getSpanId());
+ spanContextData.put(TRACE_FLAGS, spanContext.getTraceFlags().asHex());
}
- Map spanContextData = new HashMap<>();
- spanContextData.put(TRACE_ID, spanContext.getTraceId());
- spanContextData.put(SPAN_ID, spanContext.getSpanId());
- spanContextData.put(TRACE_FLAGS, spanContext.getTraceFlags().asHex());
+ if (LogbackSingletons.addBaggage()) {
+ Baggage baggage = Java8BytecodeBridge.baggageFromContext(context);
+
+ // using a lambda here does not play nicely with instrumentation bytecode process
+ // (Java 6 related errors are observed) so relying on for loop instead
+ for (Map.Entry entry : baggage.asMap().entrySet()) {
+ spanContextData.put(
+ entry.getKey(),
+ // prefix all baggage values to avoid clashes with existing context
+ "baggage." + entry.getValue().getValue());
+ }
+ }
if (contextData == null) {
contextData = spanContextData;
diff --git a/instrumentation/logback/logback-mdc-1.0/library/build.gradle.kts b/instrumentation/logback/logback-mdc-1.0/library/build.gradle.kts
index 6bf9d8c2bf2e..76537740d178 100644
--- a/instrumentation/logback/logback-mdc-1.0/library/build.gradle.kts
+++ b/instrumentation/logback/logback-mdc-1.0/library/build.gradle.kts
@@ -2,7 +2,44 @@ plugins {
id("otel.library-instrumentation")
}
+testing {
+ suites {
+ val addBaggageTest by registering(JvmTestSuite::class) {
+ targets {
+ all {
+ testTask.configure {
+ jvmArgs("-Dotel.instrumentation.logback-mdc.add-baggage=true")
+ }
+ }
+ }
+ }
+
+ withType(JvmTestSuite::class) {
+ dependencies {
+ if (findProperty("testLatestDeps") as Boolean) {
+ implementation("ch.qos.logback:logback-classic:+")
+ } else {
+ implementation("ch.qos.logback:logback-classic") {
+ version {
+ strictly("1.0.0")
+ }
+ }
+ implementation("org.slf4j:slf4j-api") {
+ version {
+ strictly("1.6.4")
+ }
+ }
+ }
+
+ implementation(project(":instrumentation:logback:logback-mdc-1.0:testing"))
+ implementation(project(":instrumentation:logback:logback-mdc-1.0:library"))
+ }
+ }
+ }
+}
+
dependencies {
+
// pin the version strictly to avoid overriding by dependencyManagement versions
compileOnly("ch.qos.logback:logback-classic") {
version {
@@ -14,21 +51,10 @@ dependencies {
strictly("1.6.4")
}
}
+}
- if (findProperty("testLatestDeps") as Boolean) {
- testImplementation("ch.qos.logback:logback-classic:+")
- } else {
- testImplementation("ch.qos.logback:logback-classic") {
- version {
- strictly("1.0.0")
- }
- }
- testImplementation("org.slf4j:slf4j-api") {
- version {
- strictly("1.6.4")
- }
- }
+tasks {
+ named("check") {
+ dependsOn(testing.suites)
}
-
- testImplementation(project(":instrumentation:logback:logback-mdc-1.0:testing"))
}
diff --git a/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/LogbackWithBaggageTest.groovy b/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/LogbackWithBaggageTest.groovy
new file mode 100644
index 000000000000..b1ddcc750212
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/LogbackWithBaggageTest.groovy
@@ -0,0 +1,12 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.logback.mdc.v1_0
+
+
+import io.opentelemetry.instrumentation.test.LibraryTestTrait
+
+class LogbackWithBaggageTest extends AbstractLogbackWithBaggageTest implements LibraryTestTrait {
+}
diff --git a/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/resources/logback.xml b/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/resources/logback.xml
new file mode 100644
index 000000000000..6d7db9d2cc18
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/library/src/addBaggageTest/resources/logback.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
diff --git a/instrumentation/logback/logback-mdc-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/OpenTelemetryAppender.java b/instrumentation/logback/logback-mdc-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/OpenTelemetryAppender.java
index 17bf842f4964..026c5ba9e2f9 100644
--- a/instrumentation/logback/logback-mdc-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/OpenTelemetryAppender.java
+++ b/instrumentation/logback/logback-mdc-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/OpenTelemetryAppender.java
@@ -15,8 +15,10 @@
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.spi.AppenderAttachable;
import ch.qos.logback.core.spi.AppenderAttachableImpl;
+import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.logback.mdc.v1_0.internal.UnionMap;
import java.lang.reflect.Proxy;
import java.util.HashMap;
@@ -25,15 +27,22 @@
public class OpenTelemetryAppender extends UnsynchronizedAppenderBase
implements AppenderAttachable {
+ private volatile boolean addBaggage;
private final AppenderAttachableImpl aai = new AppenderAttachableImpl<>();
- public static ILoggingEvent wrapEvent(ILoggingEvent event) {
- Span currentSpan = Span.current();
- if (!currentSpan.getSpanContext().isValid()) {
- return event;
- }
+ /**
+ * When set to true this will enable addition of all baggage entries to MDC. This can be done by
+ * adding the following to the logback.xml config for this appender. {@code
+ * true}
+ *
+ * @param addBaggage True if baggage should be added to MDC
+ */
+ public void setAddBaggage(boolean addBaggage) {
+ this.addBaggage = addBaggage;
+ }
+ public ILoggingEvent wrapEvent(ILoggingEvent event) {
Map eventContext = event.getMDCPropertyMap();
if (eventContext != null && eventContext.containsKey(TRACE_ID)) {
// Assume already instrumented event if traceId is present.
@@ -41,10 +50,25 @@ public static ILoggingEvent wrapEvent(ILoggingEvent event) {
}
Map contextData = new HashMap<>();
- SpanContext spanContext = currentSpan.getSpanContext();
- contextData.put(TRACE_ID, spanContext.getTraceId());
- contextData.put(SPAN_ID, spanContext.getSpanId());
- contextData.put(TRACE_FLAGS, spanContext.getTraceFlags().asHex());
+ Context context = Context.current();
+ Span currentSpan = Span.fromContext(context);
+
+ if (currentSpan.getSpanContext().isValid()) {
+ SpanContext spanContext = currentSpan.getSpanContext();
+ contextData.put(TRACE_ID, spanContext.getTraceId());
+ contextData.put(SPAN_ID, spanContext.getSpanId());
+ contextData.put(TRACE_FLAGS, spanContext.getTraceFlags().asHex());
+ }
+
+ if (addBaggage) {
+ Baggage baggage = Baggage.fromContext(context);
+ baggage.forEach(
+ (key, value) ->
+ contextData.put(
+ key,
+ // prefix all baggage values to avoid clashes with existing context
+ "baggage." + value.getValue()));
+ }
if (eventContext == null) {
eventContext = contextData;
diff --git a/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackTest.groovy b/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackTest.groovy
index 791f916332c1..0062ea09bc67 100644
--- a/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackTest.groovy
+++ b/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackTest.groovy
@@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.logback.mdc.v1_0
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.read.ListAppender
+import io.opentelemetry.api.baggage.Baggage
import io.opentelemetry.api.trace.Span
import io.opentelemetry.instrumentation.test.InstrumentationSpecification
import org.slf4j.Logger
@@ -39,8 +40,12 @@ abstract class AbstractLogbackTest extends InstrumentationSpecification {
def "no ids when no span"() {
when:
- logger.info("log message 1")
- logger.info("log message 2")
+ Baggage baggage = Baggage.empty().toBuilder().put("baggage_key", "baggage_value").build()
+
+ runWithBaggage(baggage) {
+ AbstractLogbackTest.logger.info("log message 1")
+ AbstractLogbackTest.logger.info("log message 2")
+ }
def events = listAppender.list
@@ -50,25 +55,27 @@ abstract class AbstractLogbackTest extends InstrumentationSpecification {
events[0].getMDCPropertyMap().get("trace_id") == null
events[0].getMDCPropertyMap().get("span_id") == null
events[0].getMDCPropertyMap().get("trace_flags") == null
+ events[0].getMDCPropertyMap().get("baggage_key") == (expectBaggage() ? "baggage.baggage_value" : null)
events[1].message == "log message 2"
events[1].getMDCPropertyMap().get("trace_id") == null
events[1].getMDCPropertyMap().get("span_id") == null
events[1].getMDCPropertyMap().get("trace_flags") == null
+ events[1].getMDCPropertyMap().get("baggage_key") == (expectBaggage() ? "baggage.baggage_value" : null)
}
def "ids when span"() {
when:
- Span span1 = runWithSpan("test") {
+ Baggage baggage = Baggage.empty().toBuilder().put("baggage_key", "baggage_value").build()
+
+ Span span1 = runWithSpanAndBaggage("test", baggage) {
AbstractLogbackTest.logger.info("log message 1")
- Span.current()
}
logger.info("log message 2")
- Span span2 = runWithSpan("test 2") {
+ Span span2 = runWithSpanAndBaggage("test 2", baggage) {
AbstractLogbackTest.logger.info("log message 3")
- Span.current()
}
def events = listAppender.list
@@ -79,15 +86,35 @@ abstract class AbstractLogbackTest extends InstrumentationSpecification {
events[0].getMDCPropertyMap().get("trace_id") == span1.spanContext.traceId
events[0].getMDCPropertyMap().get("span_id") == span1.spanContext.spanId
events[0].getMDCPropertyMap().get("trace_flags") == "01"
+ events[0].getMDCPropertyMap().get("baggage_key") == (expectBaggage() ? "baggage.baggage_value" : null)
events[1].message == "log message 2"
events[1].getMDCPropertyMap().get("trace_id") == null
events[1].getMDCPropertyMap().get("span_id") == null
events[1].getMDCPropertyMap().get("trace_flags") == null
+ events[1].getMDCPropertyMap().get("baggage_key") == null
events[2].message == "log message 3"
events[2].getMDCPropertyMap().get("trace_id") == span2.spanContext.traceId
events[2].getMDCPropertyMap().get("span_id") == span2.spanContext.spanId
events[2].getMDCPropertyMap().get("trace_flags") == "01"
+ events[2].getMDCPropertyMap().get("baggage_key") == (expectBaggage() ? "baggage.baggage_value" : null)
+ }
+
+ Span runWithSpanAndBaggage(String spanName, Baggage baggage, Closure callback) {
+ return runWithSpan(spanName) {
+ runWithBaggage(baggage, callback)
+ Span.current()
+ }
+ }
+
+ void runWithBaggage(Baggage baggage, Closure callback) {
+ try (var unusedScope = baggage.makeCurrent()) {
+ callback.call()
+ }
+ }
+
+ boolean expectBaggage() {
+ return false
}
}
diff --git a/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackWithBaggageTest.groovy b/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackWithBaggageTest.groovy
new file mode 100644
index 000000000000..66762efeac06
--- /dev/null
+++ b/instrumentation/logback/logback-mdc-1.0/testing/src/main/groovy/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackWithBaggageTest.groovy
@@ -0,0 +1,13 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.logback.mdc.v1_0
+
+abstract class AbstractLogbackWithBaggageTest extends AbstractLogbackTest {
+ @Override
+ boolean expectBaggage() {
+ return true
+ }
+}
diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/Java8BytecodeBridge.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/Java8BytecodeBridge.java
index 52ed8541de37..588b48e23916 100644
--- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/Java8BytecodeBridge.java
+++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/Java8BytecodeBridge.java
@@ -5,6 +5,7 @@
package io.opentelemetry.javaagent.bootstrap;
+import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
@@ -37,5 +38,9 @@ public static Span spanFromContext(Context context) {
return Span.fromContext(context);
}
+ public static Baggage baggageFromContext(Context context) {
+ return Baggage.fromContext(context);
+ }
+
private Java8BytecodeBridge() {}
}