Skip to content

Commit 34740ee

Browse files
authored
Fix caller data lost in logback mdc library instrumentation (#12220)
1 parent 103d160 commit 34740ee

File tree

2 files changed

+46
-37
lines changed

2 files changed

+46
-37
lines changed

instrumentation/logback/logback-mdc-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/OpenTelemetryAppender.java

+29-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import ch.qos.logback.classic.spi.ILoggingEvent;
99
import ch.qos.logback.classic.spi.LoggerContextVO;
10-
import ch.qos.logback.classic.spi.LoggingEventVO;
10+
import ch.qos.logback.classic.spi.LoggingEvent;
1111
import ch.qos.logback.core.Appender;
1212
import ch.qos.logback.core.UnsynchronizedAppenderBase;
1313
import ch.qos.logback.core.spi.AppenderAttachable;
@@ -18,14 +18,26 @@
1818
import io.opentelemetry.context.Context;
1919
import io.opentelemetry.instrumentation.api.incubator.log.LoggingContextConstants;
2020
import io.opentelemetry.instrumentation.logback.mdc.v1_0.internal.UnionMap;
21-
import java.lang.reflect.InvocationTargetException;
22-
import java.lang.reflect.Proxy;
21+
import java.lang.reflect.Field;
2322
import java.util.HashMap;
2423
import java.util.Iterator;
2524
import java.util.Map;
2625

2726
public class OpenTelemetryAppender extends UnsynchronizedAppenderBase<ILoggingEvent>
2827
implements AppenderAttachable<ILoggingEvent> {
28+
private static final Field MDC_MAP_FIELD;
29+
30+
static {
31+
Field field;
32+
try {
33+
field = LoggingEvent.class.getDeclaredField("mdcPropertyMap");
34+
field.setAccessible(true);
35+
} catch (Exception exception) {
36+
field = null;
37+
}
38+
MDC_MAP_FIELD = field;
39+
}
40+
2941
private boolean addBaggage;
3042
private String traceIdKey = LoggingContextConstants.TRACE_ID;
3143
private String spanIdKey = LoggingContextConstants.SPAN_ID;
@@ -59,11 +71,15 @@ public void setTraceFlagsKey(String traceFlagsKey) {
5971
this.traceFlagsKey = traceFlagsKey;
6072
}
6173

62-
public ILoggingEvent wrapEvent(ILoggingEvent event) {
74+
private void processEvent(ILoggingEvent event) {
75+
if (MDC_MAP_FIELD == null || event.getClass() != LoggingEvent.class) {
76+
return;
77+
}
78+
6379
Map<String, String> eventContext = event.getMDCPropertyMap();
6480
if (eventContext != null && eventContext.containsKey(traceIdKey)) {
6581
// Assume already instrumented event if traceId is present.
66-
return event;
82+
return;
6783
}
6884

6985
Map<String, String> contextData = new HashMap<>();
@@ -98,32 +114,18 @@ public ILoggingEvent wrapEvent(ILoggingEvent event) {
98114
? new LoggerContextVO(oldVo.getName(), eventContextMap, oldVo.getBirthTime())
99115
: null;
100116

101-
ILoggingEvent wrappedEvent =
102-
(ILoggingEvent)
103-
Proxy.newProxyInstance(
104-
ILoggingEvent.class.getClassLoader(),
105-
new Class<?>[] {ILoggingEvent.class},
106-
(proxy, method, args) -> {
107-
if ("getMDCPropertyMap".equals(method.getName())) {
108-
return eventContextMap;
109-
} else if ("getLoggerContextVO".equals(method.getName())) {
110-
return vo;
111-
}
112-
try {
113-
return method.invoke(event, args);
114-
} catch (InvocationTargetException exception) {
115-
throw exception.getCause();
116-
}
117-
});
118-
// https://github.com/qos-ch/logback/blob/9e833ec858953a2296afdc3292f8542fc08f2a45/logback-classic/src/main/java/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java#L29
119-
// LoggingEventPreSerializationTransformer accepts only subclasses of LoggingEvent and
120-
// LoggingEventVO, here we transform our wrapped event into a LoggingEventVO
121-
return LoggingEventVO.build(wrappedEvent);
117+
try {
118+
MDC_MAP_FIELD.set(event, eventContextMap);
119+
} catch (IllegalAccessException ignored) {
120+
// setAccessible(true) was called on the field
121+
}
122+
((LoggingEvent) event).setLoggerContextRemoteView(vo);
122123
}
123124

124125
@Override
125126
protected void append(ILoggingEvent event) {
126-
aai.appendLoopOnAppenders(wrapEvent(event));
127+
processEvent(event);
128+
aai.appendLoopOnAppenders(event);
127129
}
128130

129131
@Override

instrumentation/logback/logback-mdc-1.0/testing/src/main/java/io/opentelemetry/instrumentation/logback/mdc/v1_0/AbstractLogbackTest.java

+17-10
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,20 @@ void testNoIdsWhenNoSpan() {
6565

6666
assertThat(events.size()).isEqualTo(2);
6767
assertThat(events.get(0).getMessage()).isEqualTo("log message 1");
68-
assertThat(events.get(0).getMDCPropertyMap().get(getLoggingKey("trace_id"))).isNull();
69-
assertThat(events.get(0).getMDCPropertyMap().get(getLoggingKey("span_id"))).isNull();
70-
assertThat(events.get(0).getMDCPropertyMap().get(getLoggingKey("trace_flags"))).isNull();
68+
assertThat(events.get(0).getMDCPropertyMap())
69+
.doesNotContainKeys(
70+
getLoggingKey("trace_id"), getLoggingKey("span_id"), getLoggingKey("trace_flags"));
7171
assertThat(events.get(0).getMDCPropertyMap().get("baggage.baggage_key"))
7272
.isEqualTo(expectBaggage() ? "baggage_value" : null);
73+
assertThat(events.get(0).getCallerData()).isNotNull();
7374

7475
assertThat(events.get(1).getMessage()).isEqualTo("log message 2");
75-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("trace_id"))).isNull();
76-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("span_id"))).isNull();
77-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("trace_flags"))).isNull();
76+
assertThat(events.get(1).getMDCPropertyMap())
77+
.doesNotContainKeys(
78+
getLoggingKey("trace_id"), getLoggingKey("span_id"), getLoggingKey("trace_flags"));
7879
assertThat(events.get(1).getMDCPropertyMap().get("baggage.baggage_key"))
7980
.isEqualTo(expectBaggage() ? "baggage_value" : null);
81+
assertThat(events.get(1).getCallerData()).isNotNull();
8082
}
8183

8284
@Test
@@ -98,12 +100,16 @@ void testIdsWhenSpan() {
98100
assertThat(events.get(0).getMDCPropertyMap().get(getLoggingKey("trace_flags"))).isEqualTo("01");
99101
assertThat(events.get(0).getMDCPropertyMap().get("baggage.baggage_key"))
100102
.isEqualTo(expectBaggage() ? "baggage_value" : null);
103+
assertThat(events.get(0).getCallerData()).isNotNull();
101104

102105
assertThat(events.get(1).getMessage()).isEqualTo("log message 2");
103-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("trace_id"))).isNull();
104-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("span_id"))).isNull();
105-
assertThat(events.get(1).getMDCPropertyMap().get(getLoggingKey("trace_flags"))).isNull();
106-
assertThat(events.get(1).getMDCPropertyMap().get("baggage.baggage_key")).isNull();
106+
assertThat(events.get(1).getMDCPropertyMap())
107+
.doesNotContainKeys(
108+
getLoggingKey("trace_id"),
109+
getLoggingKey("span_id"),
110+
getLoggingKey("trace_flags"),
111+
"baggage.baggage_key");
112+
assertThat(events.get(1).getCallerData()).isNotNull();
107113

108114
assertThat(events.get(2).getMessage()).isEqualTo("log message 3");
109115
assertThat(events.get(2).getMDCPropertyMap().get(getLoggingKey("trace_id")))
@@ -113,6 +119,7 @@ void testIdsWhenSpan() {
113119
assertThat(events.get(2).getMDCPropertyMap().get(getLoggingKey("trace_flags"))).isEqualTo("01");
114120
assertThat(events.get(2).getMDCPropertyMap().get("baggage.baggage_key"))
115121
.isEqualTo(expectBaggage() ? "baggage_value" : null);
122+
assertThat(events.get(2).getCallerData()).isNotNull();
116123
}
117124

118125
void runWithBaggage(Baggage baggage, Runnable runnable) {

0 commit comments

Comments
 (0)