Skip to content

Commit f930598

Browse files
authored
Fix adding logback mdc appender in spring starter (#13391)
1 parent edf4abd commit f930598

File tree

5 files changed

+50
-1
lines changed

5 files changed

+50
-1
lines changed

instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ testing {
132132
implementation("org.springframework.boot:spring-boot-autoconfigure:$springBootVersion")
133133

134134
implementation(project(":instrumentation:logback:logback-appender-1.0:library"))
135+
implementation(project(":instrumentation:logback:logback-mdc-1.0:library"))
135136
// using the same versions as in the spring-boot-autoconfigure
136137
implementation("ch.qos.logback:logback-classic") {
137138
version {

instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java

+8
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ private static void addMdcAppender(
172172
initializeMdcAppenderFromProperties(applicationEnvironmentPreparedEvent, openTelemetryAppender);
173173
openTelemetryAppender.start();
174174
logger.addAppender(openTelemetryAppender);
175+
// move existing appenders under otel mdc appender, so they could observe the added mdc values
176+
for (Iterator<Appender<ILoggingEvent>> i = logger.iteratorForAppenders(); i.hasNext(); ) {
177+
Appender<ILoggingEvent> appender = i.next();
178+
if (appender != openTelemetryAppender) {
179+
openTelemetryAppender.addAppender(appender);
180+
logger.detachAppender(appender);
181+
}
182+
}
175183
}
176184

177185
private static void initializeMdcAppenderFromProperties(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging;
7+
8+
import ch.qos.logback.classic.spi.ILoggingEvent;
9+
import ch.qos.logback.core.read.ListAppender;
10+
11+
@SuppressWarnings("OtelInternalJavadoc")
12+
public class CustomListAppender extends ListAppender<ILoggingEvent> {
13+
public static boolean lastLogHadTraceId;
14+
15+
@Override
16+
protected void append(ILoggingEvent event) {
17+
// Since list appender just captures the event object it is possible that the trace_id is not
18+
// present when list appender was called but is added at a later time. Here we record whether
19+
// trace_id was present in mdc at the time when the event was processed by the list appender.
20+
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/13383
21+
lastLogHadTraceId = event.getMDCPropertyMap().get("trace_id") != null;
22+
super.append(event);
23+
}
24+
}

instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderTest.java

+16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.assertj.core.api.Assertions.assertThat;
99

1010
import ch.qos.logback.classic.spi.ILoggingEvent;
11+
import ch.qos.logback.core.Appender;
1112
import ch.qos.logback.core.read.ListAppender;
1213
import ch.qos.logback.core.spi.AppenderAttachable;
1314
import io.opentelemetry.api.OpenTelemetry;
@@ -22,6 +23,7 @@
2223
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
2324
import io.opentelemetry.sdk.logs.data.LogRecordData;
2425
import java.util.HashMap;
26+
import java.util.Iterator;
2527
import java.util.List;
2628
import java.util.Map;
2729
import org.junit.jupiter.api.BeforeEach;
@@ -191,6 +193,7 @@ void shouldInitializeMdcAppender() {
191193
}
192194

193195
assertThat(testing.logRecords()).isEmpty();
196+
assertThat(CustomListAppender.lastLogHadTraceId).isTrue();
194197
assertThat(listAppender.list)
195198
.satisfiesExactly(
196199
event ->
@@ -238,13 +241,26 @@ void shouldNotInitializeMdcAppenderWhenDisabled() {
238241
private static ListAppender<ILoggingEvent> getListAppender() {
239242
Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
240243
ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) logger;
244+
241245
ListAppender<ILoggingEvent> listAppender =
242246
(ListAppender<ILoggingEvent>) logbackLogger.getAppender("List");
243247
if (listAppender != null) {
244248
return listAppender;
245249
}
250+
246251
AppenderAttachable<?> mdcAppender =
247252
(AppenderAttachable<?>) logbackLogger.getAppender("OpenTelemetryMdc");
253+
if (mdcAppender == null) {
254+
for (Iterator<Appender<ILoggingEvent>> i = logbackLogger.iteratorForAppenders();
255+
i.hasNext(); ) {
256+
Appender<ILoggingEvent> appender = i.next();
257+
if (appender
258+
instanceof io.opentelemetry.instrumentation.logback.mdc.v1_0.OpenTelemetryAppender) {
259+
mdcAppender = (AppenderAttachable<?>) appender;
260+
break;
261+
}
262+
}
263+
}
248264
return (ListAppender<ILoggingEvent>) mdcAppender.getAppender("List");
249265
}
250266
}

instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/resources/logback-no-otel-appenders.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</pattern>
99
</encoder>
1010
</appender>
11-
<appender name="List" class="ch.qos.logback.core.read.ListAppender" />
11+
<appender name="List" class="io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.CustomListAppender" />
1212

1313
<root level="INFO">
1414
<appender-ref ref="console"/>

0 commit comments

Comments
 (0)