package brave.features.log4j2_context;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.propagation.CurrentTraceContext;
import brave.propagation.TraceContext;
import org.apache.logging.log4j.ThreadContext;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class Log4JThreadContextTest {
/**
* One common request is to support SLF4J or Log4J2 log correlation. This shows you can make a
* custom implementation
*/
@Test public void customCurrentTraceContext() {
assertThat(ThreadContext.get("traceID"))
.isNull();
Tracer tracer = Tracing.newBuilder()
.currentTraceContext(new Log4J2CurrentTraceContext()).build().tracer();
Span parent = tracer.newTrace();
try (Tracer.SpanInScope wsParent = tracer.withSpanInScope(parent)) {
// the trace id is now in the logging context
assertThat(ThreadContext.get("traceId"))
.isEqualTo(parent.context().traceIdString());
// Clear a scope temporarily
try (Tracer.SpanInScope noScope = tracer.withSpanInScope(null)) {
assertThat(tracer.currentSpan())
.isNull();
}
Span child = tracer.newChild(parent.context());
try (Tracer.SpanInScope wsChild = tracer.withSpanInScope(child)) {
// nesting worked
assertThat(ThreadContext.get("traceId"))
.isEqualTo(child.context().traceIdString());
}
// old parent reverted
assertThat(ThreadContext.get("traceId"))
.isEqualTo(parent.context().traceIdString());
}
assertThat(ThreadContext.get("traceId"))
.isNull();
}
static class Log4J2CurrentTraceContext extends CurrentTraceContext {
CurrentTraceContext delegate = new CurrentTraceContext.Default();
@Override public TraceContext get() {
return delegate.get();
}
@Override public Scope newScope(TraceContext currentSpan) {
final String previousTraceId = ThreadContext.get("traceId");
if (currentSpan != null) {
ThreadContext.put("traceId", currentSpan.traceIdString());
} else {
ThreadContext.remove("traceId");
}
Scope scope = delegate.newScope(currentSpan);
return () -> {
scope.close();
ThreadContext.put("traceId", previousTraceId);
};
}
}
}