Skip to content

Commit 544e815

Browse files
authored
Merge pull request #84 from newrelic/fix-mdc-logback
Fix mdc logback
2 parents 23e4825 + 8819ac0 commit 544e815

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

examples/logback-app/build.gradle.kts

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ repositories {
1212

1313
dependencies {
1414
implementation(project(":logback"))
15-
implementation("ch.qos.logback:logback-core:1.2.3")
16-
implementation("ch.qos.logback:logback-classic:1.2.3")
15+
implementation("ch.qos.logback:logback-core:1.3.9")
16+
implementation("ch.qos.logback:logback-classic:1.3.9")
1717
implementation("com.fasterxml.jackson.core:jackson-core:2.11.1")
1818

19-
implementation("com.newrelic.agent.java:newrelic-api:7.6.0")
19+
implementation("com.newrelic.agent.java:newrelic-api:8.6.0")
2020
}
2121

2222

logback/build.gradle.kts

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ dependencies {
2727

2828
includeInJar(project(":core"))
2929

30+
testImplementation("ch.qos.logback:logback-core:1.3.9");
31+
testImplementation("ch.qos.logback:logback-classic:1.3.9");
3032
testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
3133
testImplementation("com.google.guava:guava:30.0-jre")
3234
testImplementation("org.mockito:mockito-core:3.4.4")

logback/src/main/java/com/newrelic/logging/logback/NewRelicAsyncAppender.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ public class NewRelicAsyncAppender extends AsyncAppender {
4040
protected void preprocess(ILoggingEvent eventObject) {
4141
Map<String, String> linkingMetadata = agentSupplier.get().getLinkingMetadata();
4242
// NR linking metadata is added to the MDC map
43-
if (!isNoOpMDC) {
43+
if (!IsNoOpMDCHolder.isNoOpMDC) {
4444
for (Map.Entry<String, String> entry : linkingMetadata.entrySet()) {
4545
MDC.put(NEW_RELIC_PREFIX + entry.getKey(), entry.getValue());
4646
}
4747
}
4848
super.preprocess(eventObject);
49-
if (isNoOpMDC) {
49+
if (IsNoOpMDCHolder.isNoOpMDC) {
5050
for (Map.Entry<String, String> entry : linkingMetadata.entrySet()) {
5151
/*
5252
* This only works if there is at least one entry in the MDC map. If the MDC map is empty when
@@ -59,8 +59,14 @@ protected void preprocess(ILoggingEvent eventObject) {
5959
}
6060
}
6161

62+
/*
63+
Due to issues with simultaneous classloading of the NRAsyncAppender and the Logback classes,
64+
the isNoOpMDC field is wrapped to load it lazily. Visible for testing.
65+
*/
66+
static class IsNoOpMDCHolder {
67+
static boolean isNoOpMDC = MDC.getMDCAdapter() instanceof NOPMDCAdapter;
68+
}
69+
6270
//visible for testing
6371
public static Supplier<Agent> agentSupplier = NewRelic::getAgent;
64-
@SuppressWarnings("WeakerAccess") //visible for testing
65-
static boolean isNoOpMDC = MDC.getMDCAdapter() instanceof NOPMDCAdapter;
6672
}

logback/src/test/java/com/newrelic/logging/logback/NewRelicLogbackTests.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.junit.jupiter.api.Test;
2323
import org.junit.jupiter.api.Timeout;
2424
import org.mockito.Mockito;
25+
import org.slf4j.LoggerFactory;
2526
import org.slf4j.MDC;
2627

2728
import java.io.BufferedReader;
@@ -30,6 +31,7 @@
3031
import java.io.PipedInputStream;
3132
import java.io.PipedOutputStream;
3233
import java.nio.charset.StandardCharsets;
34+
import java.util.HashMap;
3335
import java.util.function.Supplier;
3436
import java.util.regex.Pattern;
3537

@@ -60,8 +62,8 @@ void shouldWrapJsonConsoleAppenderCorrectly() throws Throwable {
6062
void shouldAllWorkCorrectlyEvenWithoutMDC() throws Throwable {
6163
givenMockAgentData();
6264
givenARedirectedAppender();
63-
givenMDCIsANoOp();
6465
givenALoggingEventWithMDCDisabled();
66+
givenMDCIsANoOp();
6567
whenTheEventIsAppended();
6668
thenMockAgentDataIsInTheMessage();
6769
thenJsonLayoutWasUsed();
@@ -129,13 +131,16 @@ private void givenMockAgentData() {
129131
}
130132

131133
private void givenMDCIsANoOp() {
132-
NewRelicAsyncAppender.isNoOpMDC = true;
134+
NewRelicAsyncAppender.IsNoOpMDCHolder.isNoOpMDC = true;
135+
// Wipe the MDC to mimic a NOPMDCAdapter.
136+
event.setMDCPropertyMap(new HashMap<>());
133137
}
134138

135139
private void givenALoggingEvent() {
136140
event = new LoggingEvent();
137141
event.setMessage("test_error_message");
138142
event.setLevel(Level.ERROR);
143+
event.setLoggerContext((LoggerContext) LoggerFactory.getILoggerFactory());
139144
}
140145

141146
private void givenALoggingEventWithExceptionData() {
@@ -283,7 +288,7 @@ private String getOutput() throws IOException {
283288
void setUp() throws Exception {
284289
// Clear MDC data before each test
285290
MDC.clear();
286-
isNoOpMDC = NewRelicAsyncAppender.isNoOpMDC;
291+
isNoOpMDC = NewRelicAsyncAppender.IsNoOpMDCHolder.isNoOpMDC;
287292
outputStream = new PipedOutputStream();
288293
PipedInputStream inputStream = new PipedInputStream(outputStream);
289294
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
@@ -293,7 +298,7 @@ void setUp() throws Exception {
293298
void tearDown() throws Exception {
294299
// Clear MDC data before each test
295300
MDC.clear();
296-
NewRelicAsyncAppender.isNoOpMDC = isNoOpMDC;
301+
NewRelicAsyncAppender.IsNoOpMDCHolder.isNoOpMDC = isNoOpMDC;
297302
appender.stop();
298303
appender.detachAndStopAllAppenders();
299304
outputStream.close();

0 commit comments

Comments
 (0)