Add support for log4j 1.x
This commit is contained in:
parent
8d562f91fd
commit
dcf0f57030
|
@ -128,6 +128,7 @@ public class AgentInstaller {
|
|||
.or(nameStartsWith("com.jinspired."))
|
||||
.or(nameStartsWith("org.jinspired."))
|
||||
.or(nameStartsWith("org.apache.log4j."))
|
||||
.and(not(named("org.apache.log4j.MDC")))
|
||||
.or(nameStartsWith("org.slf4j.").and(not(named("org.slf4j.MDC"))))
|
||||
.or(nameContains("$JaxbAccessor"))
|
||||
.or(nameContains("CGLIB$$"))
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
apply from: "${rootDir}/gradle/java.gradle"
|
||||
|
||||
ext {
|
||||
log4jVersion = '1.2.17'
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group = 'log4j'
|
||||
module = 'log4j'
|
||||
versions = '(,)'
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
// In order to test the real log4j library we need to remove the log4j transitive dependency
|
||||
// dependency brought in by :dd-java-agent:testing over 'log4j-over-slf4j' which would shadow
|
||||
// the log4j module under test.
|
||||
testCompile.exclude group: 'org.slf4j', module: 'log4j-over-slf4j'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':dd-trace-api')
|
||||
compile project(':dd-java-agent:agent-tooling')
|
||||
|
||||
testCompile group: 'log4j', name: 'log4j', version: log4jVersion
|
||||
|
||||
compile deps.bytebuddy
|
||||
compile deps.opentracing
|
||||
annotationProcessor deps.autoservice
|
||||
implementation deps.autoservice
|
||||
|
||||
testCompile project(':dd-java-agent:testing')
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package datadog.trace.instrumentation.log4j1;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import datadog.trace.agent.tooling.Instrumenter;
|
||||
import datadog.trace.api.Config;
|
||||
import datadog.trace.api.CorrelationIdentifier;
|
||||
import datadog.trace.api.GlobalTracer;
|
||||
import datadog.trace.context.ScopeListener;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public class Log4j1MDCInstrumentation extends Instrumenter.Default {
|
||||
public static final String MDC_INSTRUMENTATION_NAME = "log4j-mdc";
|
||||
|
||||
private static final String mdcClassName = "org.apache.log4j.MDC";
|
||||
|
||||
public Log4j1MDCInstrumentation() {
|
||||
super(MDC_INSTRUMENTATION_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean defaultEnabled() {
|
||||
return Config.getBooleanSettingFromEnvironment(
|
||||
Config.LOGS_INJECTION_ENABLED, Config.DEFAULT_LOGS_INJECTION_ENABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher<? super TypeDescription> typeMatcher() {
|
||||
return named(mdcClassName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||
return singletonMap(isConstructor(), MDCContextAdvice.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] helperClassNames() {
|
||||
return new String[] {MDCContextAdvice.class.getName() + "$MDCScopeListener"};
|
||||
}
|
||||
|
||||
public static class MDCContextAdvice {
|
||||
@Advice.OnMethodExit(suppress = Throwable.class)
|
||||
public static void mdcClassInitialized(@Advice.This Object instance) {
|
||||
try {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> mdcClass = instance.getClass();
|
||||
final Method putMethod = mdcClass.getMethod("put", String.class, Object.class);
|
||||
final Method removeMethod = mdcClass.getMethod("remove", String.class);
|
||||
GlobalTracer.get().addScopeListener(new MDCScopeListener(putMethod, removeMethod));
|
||||
} catch (final NoSuchMethodException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
public static class MDCScopeListener implements ScopeListener {
|
||||
private final Method putMethod;
|
||||
private final Method removeMethod;
|
||||
|
||||
public MDCScopeListener(final Method putMethod, final Method removeMethod) {
|
||||
System.out.println("Initializing scope listener");
|
||||
this.putMethod = putMethod;
|
||||
this.removeMethod = removeMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterScopeActivated() {
|
||||
try {
|
||||
putMethod.invoke(
|
||||
null, CorrelationIdentifier.getTraceIdKey(), CorrelationIdentifier.getTraceId());
|
||||
putMethod.invoke(
|
||||
null, CorrelationIdentifier.getSpanIdKey(), CorrelationIdentifier.getSpanId());
|
||||
} catch (final Exception e) {
|
||||
log.debug("Exception setting thread context context", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterScopeClosed() {
|
||||
try {
|
||||
removeMethod.invoke(null, CorrelationIdentifier.getTraceIdKey());
|
||||
removeMethod.invoke(null, CorrelationIdentifier.getSpanIdKey());
|
||||
} catch (final Exception e) {
|
||||
log.debug("Exception removing thread context context", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package datadoggggg.trace.instrumentation.log4j1.something;
|
||||
|
||||
public class SomeClass {
|
||||
|
||||
private static SomeClass instance = new SomeClass();
|
||||
|
||||
public SomeClass() {
|
||||
System.out.println("SomeClass Constructor.......!!!!!!!");
|
||||
}
|
||||
|
||||
public static void put() {
|
||||
instance.doSomething();
|
||||
}
|
||||
|
||||
public void doSomething() {
|
||||
System.out.println("SomeClass Doing something............");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
import datadog.trace.agent.test.AgentTestRunner
|
||||
import datadog.trace.agent.test.utils.ConfigUtils
|
||||
import datadog.trace.api.CorrelationIdentifier
|
||||
import io.opentracing.Scope
|
||||
import io.opentracing.util.GlobalTracer
|
||||
import org.apache.log4j.MDC
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
class Log4j1MDCTest extends AgentTestRunner {
|
||||
|
||||
static {
|
||||
System.setProperty("dd.logs.injection", "true")
|
||||
}
|
||||
|
||||
def "MDC shows trace and span ids for active scope"() {
|
||||
|
||||
when:
|
||||
MDC.put("foo", "bar")
|
||||
Scope rootScope = GlobalTracer.get().buildSpan("root").startActive(true)
|
||||
|
||||
then:
|
||||
MDC.get(CorrelationIdentifier.getTraceIdKey()) == CorrelationIdentifier.getTraceId()
|
||||
MDC.get(CorrelationIdentifier.getSpanIdKey()) == CorrelationIdentifier.getSpanId()
|
||||
MDC.get("foo") == "bar"
|
||||
|
||||
when:
|
||||
Scope childScope = GlobalTracer.get().buildSpan("child").startActive(true)
|
||||
|
||||
then:
|
||||
MDC.get(CorrelationIdentifier.getTraceIdKey()) == CorrelationIdentifier.getTraceId()
|
||||
MDC.get(CorrelationIdentifier.getSpanIdKey()) == CorrelationIdentifier.getSpanId()
|
||||
MDC.get("foo") == "bar"
|
||||
|
||||
when:
|
||||
childScope.close()
|
||||
|
||||
then:
|
||||
MDC.get(CorrelationIdentifier.getTraceIdKey()) == CorrelationIdentifier.getTraceId()
|
||||
MDC.get(CorrelationIdentifier.getSpanIdKey()) == CorrelationIdentifier.getSpanId()
|
||||
MDC.get("foo") == "bar"
|
||||
|
||||
when:
|
||||
rootScope.close()
|
||||
|
||||
then:
|
||||
MDC.get(CorrelationIdentifier.getTraceIdKey()) == null
|
||||
MDC.get(CorrelationIdentifier.getSpanIdKey()) == null
|
||||
MDC.get("foo") == "bar"
|
||||
}
|
||||
|
||||
def "MDC context scoped by thread"() {
|
||||
setup:
|
||||
ConfigUtils.updateConfig {
|
||||
System.setProperty("dd.logs.injection", "true")
|
||||
}
|
||||
AtomicReference<Object> thread1TraceId = new AtomicReference<>()
|
||||
AtomicReference<Object> thread2TraceId = new AtomicReference<>()
|
||||
|
||||
final Thread thread1 = new Thread() {
|
||||
@Override
|
||||
void run() {
|
||||
// no trace in scope
|
||||
thread1TraceId.set(MDC.get(CorrelationIdentifier.getTraceIdKey()))
|
||||
}
|
||||
}
|
||||
|
||||
final Thread thread2 = new Thread() {
|
||||
@Override
|
||||
void run() {
|
||||
// other trace in scope
|
||||
final Scope thread2Scope = GlobalTracer.get().buildSpan("root2").startActive(true)
|
||||
try {
|
||||
thread2TraceId.set(MDC.get(CorrelationIdentifier.getTraceIdKey()))
|
||||
} finally {
|
||||
thread2Scope.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
final Scope mainScope = GlobalTracer.get().buildSpan("root").startActive(true)
|
||||
thread1.start()
|
||||
thread2.start()
|
||||
final String mainThreadTraceId = MDC.get(CorrelationIdentifier.getTraceIdKey())
|
||||
final String expectedMainThreadTraceId = CorrelationIdentifier.getTraceId()
|
||||
|
||||
thread1.join()
|
||||
thread2.join()
|
||||
|
||||
expect:
|
||||
mainThreadTraceId == expectedMainThreadTraceId
|
||||
thread1TraceId.get() == null
|
||||
thread2TraceId.get() != null
|
||||
thread2TraceId.get() != mainThreadTraceId
|
||||
|
||||
cleanup:
|
||||
mainScope?.close()
|
||||
}
|
||||
}
|
|
@ -4,6 +4,13 @@ ext {
|
|||
log4jVersion = '2.11.2'
|
||||
}
|
||||
|
||||
configurations {
|
||||
// In order to test the real log4j library we need to remove the log4j transitive dependency
|
||||
// dependency brought in by :dd-java-agent:testing over 'log4j-over-slf4j' which would shadow
|
||||
// the log4j module under test.
|
||||
testCompile.exclude group: 'org.slf4j', module: 'log4j-over-slf4j'
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group = 'org.apache.logging.log4j'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package datadog.trace.instrumentation.log4j;
|
||||
package datadog.trace.instrumentation.log4j2;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer;
|
|
@ -66,6 +66,7 @@ include ':dd-java-agent:instrumentation:jsp-2.3'
|
|||
include ':dd-java-agent:instrumentation:kafka-clients-0.11'
|
||||
include ':dd-java-agent:instrumentation:kafka-streams-0.11'
|
||||
include ':dd-java-agent:instrumentation:lettuce-5'
|
||||
include ':dd-java-agent:instrumentation:log4j1'
|
||||
include ':dd-java-agent:instrumentation:log4j2'
|
||||
include ':dd-java-agent:instrumentation:mongo'
|
||||
include ':dd-java-agent:instrumentation:mongo:driver-3.1'
|
||||
|
|
Loading…
Reference in New Issue