Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Baggage to logback MDC controlled by flag #7892

Merged
merged 13 commits into from
Mar 9, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -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"))

Expand All @@ -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"))
}
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="LIST" class="ch.qos.logback.core.read.ListAppender" />

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>

<logger name="test">
<level value="info" />
<appender-ref ref="LIST" />
</logger>

<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -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() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String, String> contextData) {

if (contextData != null && contextData.containsKey(TRACE_ID)) {
// Assume already instrumented event if traceId is present.
return;
Expand All @@ -69,15 +71,28 @@ public static void onExit(
return;
}

Map<String, String> 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<String, String> 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);
adamleantech marked this conversation as resolved.
Show resolved Hide resolved

// 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<String, BaggageEntry> 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;
Expand Down
56 changes: 41 additions & 15 deletions instrumentation/logback/logback-mdc-1.0/library/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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"))
}
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright The OpenTelemetry Authors
~
~ Licensed 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.
-->

<configuration>
<appender name="LIST" class="ch.qos.logback.core.read.ListAppender"/>

<appender name="OTEL"
class="io.opentelemetry.instrumentation.logback.mdc.v1_0.OpenTelemetryAppender">
<addBaggage>true</addBaggage>
<appender-ref ref="LIST"/>
</appender>

<logger name="test">
<level value="info"/>
<appender-ref ref="OTEL"/>
</logger>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,26 +27,48 @@

public class OpenTelemetryAppender extends UnsynchronizedAppenderBase<ILoggingEvent>
implements AppenderAttachable<ILoggingEvent> {
private volatile boolean addBaggage;
adamleantech marked this conversation as resolved.
Show resolved Hide resolved

private final AppenderAttachableImpl<ILoggingEvent> 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
* <addBaggage>true</addBaggage>}
*
* @param addBaggage True if baggage should be added to MDC
*/
public void setAddBaggage(boolean addBaggage) {
adamleantech marked this conversation as resolved.
Show resolved Hide resolved
this.addBaggage = addBaggage;
}

public ILoggingEvent wrapEvent(ILoggingEvent event) {
Map<String, String> eventContext = event.getMDCPropertyMap();
if (eventContext != null && eventContext.containsKey(TRACE_ID)) {
// Assume already instrumented event if traceId is present.
return event;
}

Map<String, String> 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;
Expand Down
Loading