Remove jre logging integration

This commit is contained in:
Andrew Kent 2019-01-16 08:59:10 -08:00
parent 3295739e28
commit 6ffaa9e04f
4 changed files with 0 additions and 269 deletions

View File

@ -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')
}

View File

@ -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.
*
* <p>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<ClassLoader>() {
@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.
*
* <p>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},
"<init>",
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<FieldDescription.InDefinedShape> 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),
"<init>",
"(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;
}
};
}
}
}

View File

@ -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"
}
}

View File

@ -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'