diff --git a/dd-java-agent/instrumentation/jre-logging/jre-logging.gradle b/dd-java-agent/instrumentation/jre-logging/jre-logging.gradle deleted file mode 100644 index d34123ed49..0000000000 --- a/dd-java-agent/instrumentation/jre-logging/jre-logging.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Set properties before any plugins get loaded -project.ext { - // Execute tests on all JVMs, even rare and outdated ones - coreJavaInstrumentation = true -} - -apply from: "${rootDir}/gradle/java.gradle" - -dependencies { - compile project(':dd-trace-api') - compile project(':dd-java-agent:agent-tooling') - - compile deps.bytebuddy - compile deps.opentracing - annotationProcessor deps.autoservice - implementation deps.autoservice - - testCompile project(':dd-java-agent:testing') -} diff --git a/dd-java-agent/instrumentation/jre-logging/src/main/java/datadog/trace/instrumentation/jre/logging/LoggerInstrumentation.java b/dd-java-agent/instrumentation/jre-logging/src/main/java/datadog/trace/instrumentation/jre/logging/LoggerInstrumentation.java deleted file mode 100644 index d11317fa2b..0000000000 --- a/dd-java-agent/instrumentation/jre-logging/src/main/java/datadog/trace/instrumentation/jre/logging/LoggerInstrumentation.java +++ /dev/null @@ -1,223 +0,0 @@ -package datadog.trace.instrumentation.jre.logging; - -import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.failSafe; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import datadog.trace.agent.tooling.ClassLoaderMatcher; -import datadog.trace.agent.tooling.Instrumenter; -import datadog.trace.agent.tooling.Utils; -import datadog.trace.agent.tooling.muzzle.Reference; -import datadog.trace.agent.tooling.muzzle.ReferenceMatcher; -import java.security.ProtectionDomain; -import lombok.extern.slf4j.Slf4j; -import net.bytebuddy.agent.builder.AgentBuilder; -import net.bytebuddy.asm.AsmVisitorWrapper; -import net.bytebuddy.description.field.FieldDescription; -import net.bytebuddy.description.field.FieldList; -import net.bytebuddy.description.method.MethodList; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.dynamic.DynamicType; -import net.bytebuddy.implementation.Implementation; -import net.bytebuddy.jar.asm.ClassVisitor; -import net.bytebuddy.jar.asm.ClassWriter; -import net.bytebuddy.jar.asm.Label; -import net.bytebuddy.jar.asm.MethodVisitor; -import net.bytebuddy.jar.asm.Opcodes; -import net.bytebuddy.jar.asm.Type; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.pool.TypePool; -import net.bytebuddy.utility.JavaModule; - -/** - * This instrumentation patches java.util.logging.Logger to return a "safe" logger which doesn't - * touch the global log manager when static log creators (e.g. getLogger) are invoked under datadog - * threads. - * - *

Our PatchLogger solution is not enough here because it's possible for dd-threads to use - * bootstrap utils which in turn use call Logger.getLogger(...) - */ -@Slf4j -@AutoService(Instrumenter.class) -public class LoggerInstrumentation implements Instrumenter { - // Intentionally doing the string replace to bypass gradle shadow rename - // loggerClassName = java.util.logging.Logger - private static final String loggerClassName = - "java.util.logging.TMP".replaceFirst("TMP", "Logger"); - private ReferenceMatcher referenceMatcher = null; - - public LoggerInstrumentation() {} - - @Override - public AgentBuilder instrument(AgentBuilder agentBuilder) { - return agentBuilder - .type( - failSafe( - named(loggerClassName), - "Instrumentation type matcher unexpected exception: " + getClass().getName()), - failSafe( - new ElementMatcher() { - @Override - public boolean matches(ClassLoader target) { - return target == ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER; - } - }, - "Instrumentation class loader matcher unexpected exception: " - + getClass().getName())) - .and( - new AgentBuilder.RawMatcher() { - @Override - public boolean matches( - TypeDescription typeDescription, - ClassLoader classLoader, - JavaModule module, - Class classBeingRedefined, - ProtectionDomain protectionDomain) { - // make sure the private constructor is present before applying instrumentation. - return getReferenceMatcher().matches(classLoader); - } - }) - .transform( - new AgentBuilder.Transformer() { - @Override - public DynamicType.Builder transform( - DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, - JavaModule module) { - return builder.visit(new ReturnPatchLoggerForDDThreadsVisitor()); - } - }); - } - - /** - * Create or build a muzzle reference matcher to assert private logging constructor is present. - * - *

Logging instrumentation uses this private constructor because it's the only path to create a - * logger which does not touch the global log manager. - */ - private synchronized ReferenceMatcher getReferenceMatcher() { - if (null == referenceMatcher) { - referenceMatcher = - new ReferenceMatcher( - new Reference.Builder(loggerClassName) - .withMethod( - new Reference.Source[0], - new Reference.Flag[] {Reference.Flag.PRIVATE_OR_HIGHER}, - "", - Type.VOID_TYPE, - Type.getType(String.class)) - .build()); - } - return referenceMatcher; - } - - /** - * Replace java.util.logging.Logger#getLogger() methods with an early-return for datadog threads - * to avoid initializing the global log manager. - */ - private static class ReturnPatchLoggerForDDThreadsVisitor implements AsmVisitorWrapper { - @Override - public int mergeWriter(int flags) { - return flags | ClassWriter.COMPUTE_MAXS; - } - - @Override - public int mergeReader(int flags) { - return flags; - } - - @Override - public ClassVisitor wrap( - TypeDescription instrumentedType, - ClassVisitor classVisitor, - Implementation.Context implementationContext, - TypePool typePool, - FieldList fields, - MethodList methods, - int writerFlags, - int readerFlags) { - return new ClassVisitor(Opcodes.ASM7, classVisitor) { - @Override - public void visit( - int version, - int access, - String name, - String signature, - String superName, - String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public MethodVisitor visitMethod( - int access, - final String methodName, - final String methodDesc, - String signature, - String[] exceptions) { - final MethodVisitor mv = - super.visitMethod(access, methodName, methodDesc, signature, exceptions); - // if isStatic and returns a logger, then add our advice - if ((access & Opcodes.ACC_STATIC) != 0) { - final Type returnType = Type.getReturnType(methodDesc); - if (returnType != null - && returnType.getSort() == Type.OBJECT - && returnType.getInternalName().equals(Utils.getInternalName(loggerClassName))) { - return new MethodVisitor(Opcodes.ASM7, mv) { - @Override - public void visitCode() { - /* Appends an early return to the method body for datadog threads: - * - * if (Thread.currentThread().getName().startsWith("dd-")) { - * // intentionally invoke private constructor to avoid initializing the LogManager - * return new Logger("datadog"); - * } - * // original method body - */ - final Label originalMethodBody = new Label(); - mv.visitMethodInsn( - Opcodes.INVOKESTATIC, - "java/lang/Thread", - "currentThread", - "()Ljava/lang/Thread;", - false); - mv.visitMethodInsn( - Opcodes.INVOKEVIRTUAL, - "java/lang/Thread", - "getName", - "()Ljava/lang/String;", - false); - // TODO: move dd- prefix to a constant once agent-bootstrap project is visible to - // all subprojects - mv.visitLdcInsn("dd-"); - mv.visitMethodInsn( - Opcodes.INVOKEVIRTUAL, - "java/lang/String", - "startsWith", - "(Ljava/lang/String;)Z", - false); - mv.visitJumpInsn(Opcodes.IFEQ, originalMethodBody); - mv.visitTypeInsn(Opcodes.NEW, Utils.getInternalName(loggerClassName)); - mv.visitInsn(Opcodes.DUP); - mv.visitLdcInsn("datadog-logger"); - mv.visitMethodInsn( - Opcodes.INVOKESPECIAL, - Utils.getInternalName(loggerClassName), - "", - "(Ljava/lang/String;)V", - false); - mv.visitInsn(Opcodes.ARETURN); - mv.visitLabel(originalMethodBody); - mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - super.visitCode(); - } - }; - } - } - return mv; - } - }; - } - } -} diff --git a/dd-java-agent/instrumentation/jre-logging/src/test/groovy/LoggerPatchTest.groovy b/dd-java-agent/instrumentation/jre-logging/src/test/groovy/LoggerPatchTest.groovy deleted file mode 100644 index c3b38d8896..0000000000 --- a/dd-java-agent/instrumentation/jre-logging/src/test/groovy/LoggerPatchTest.groovy +++ /dev/null @@ -1,26 +0,0 @@ -import datadog.trace.agent.test.AgentTestRunner - -import java.util.logging.Logger - -class LoggerPatchTest extends AgentTestRunner { - def "datadog threads receive custom logger"() { - setup: - String threadName = Thread.currentThread().getName() - Thread.currentThread().setName("dd-test") - Logger log = Logger.getLogger("foobar") - - expect: - log.getName() == "datadog-logger" - - cleanup: - Thread.currentThread().setName(threadName) - } - - def "normal threads can reach the normal logger"() { - setup: - Logger log = Logger.getLogger("foobar") - - expect: - log.getName() == "foobar" - } -} diff --git a/settings.gradle b/settings.gradle index 849c8d3291..196c24a25b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -50,7 +50,6 @@ include ':dd-java-agent:instrumentation:jdbc' include ':dd-java-agent:instrumentation:jedis-1.4' include ':dd-java-agent:instrumentation:jetty-8' include ':dd-java-agent:instrumentation:jms' -include ':dd-java-agent:instrumentation:jre-logging' 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'