/* * Copyright 2017 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.datadoghq.agent; import static dd.trace.ClassLoaderMatcher.classLoaderWithName; import static dd.trace.ClassLoaderMatcher.isReflectionClassLoader; import static net.bytebuddy.matcher.ElementMatchers.any; import static net.bytebuddy.matcher.ElementMatchers.isBootstrapClassLoader; import static net.bytebuddy.matcher.ElementMatchers.nameContains; import static net.bytebuddy.matcher.ElementMatchers.nameMatches; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import com.datadoghq.trace.DDTraceAnnotationsInfo; import com.datadoghq.trace.DDTraceInfo; import dd.trace.Instrumenter; import io.opentracing.Tracer; import io.opentracing.contrib.tracerresolver.TracerResolver; import io.opentracing.util.GlobalTracer; import java.lang.instrument.Instrumentation; import java.util.ServiceLoader; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.utility.JavaModule; /** Entry point for initializing the agent. */ @Slf4j public class TracingAgent { /** Return the classloader the core agent is running on. */ public static ClassLoader getAgentClassLoader() { return TracingAgent.class.getClassLoader(); } public static void premain(String agentArgs, final Instrumentation inst) throws Exception { log.debug("Using premain for loading {}", TracingAgent.class.getSimpleName()); addByteBuddy(inst); initializeGlobalTracer(); } public static void agentmain(final String agentArgs, final Instrumentation inst) throws Exception { log.debug("Using agentmain for loading {}", TracingAgent.class.getSimpleName()); addByteBuddy(inst); initializeGlobalTracer(); } private static synchronized void initializeGlobalTracer() { // version classes log important info // in static initializers DDJavaAgentInfo.VERSION.toString(); DDTraceInfo.VERSION.toString(); DDTraceAnnotationsInfo.VERSION.toString(); if (!GlobalTracer.isRegistered()) { // Try to obtain a tracer using the TracerResolver final Tracer resolved = TracerResolver.resolveTracer(); if (resolved != null) { try { GlobalTracer.register(resolved); } catch (final RuntimeException re) { log.warn("Failed to register tracer '" + resolved + "'", re); } } else { log.warn("Failed to resolve dd tracer"); } } } public static void addByteBuddy(final Instrumentation inst) { AgentBuilder agentBuilder = new AgentBuilder.Default() .disableClassFormatChanges() .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) .with(new Listener()) .ignore(nameStartsWith("com.datadoghq.agent.integration")) .or(nameStartsWith("dd.trace")) .or(nameStartsWith("dd.inst")) .or(nameStartsWith("dd.deps")) .or(nameStartsWith("java.")) .or(nameStartsWith("com.sun.")) .or(nameStartsWith("sun.")) .or(nameStartsWith("jdk.")) .or(nameStartsWith("org.aspectj.")) .or(nameStartsWith("org.groovy.")) .or(nameStartsWith("com.p6spy.")) .or(nameStartsWith("org.slf4j.")) .or(nameContains("javassist")) .or(nameContains(".asm.")) .or(nameMatches("com\\.mchange\\.v2\\.c3p0\\..*Proxy")) .ignore( any(), isBootstrapClassLoader() .or(isReflectionClassLoader()) .or( classLoaderWithName( "org.codehaus.groovy.runtime.callsite.CallSiteClassLoader"))); for (final Instrumenter instrumenter : ServiceLoader.load(Instrumenter.class)) { agentBuilder = instrumenter.instrument(agentBuilder); } agentBuilder.installOn(inst); } @Slf4j static class Listener implements AgentBuilder.Listener { @Override public void onError( final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded, final Throwable throwable) { log.debug("Failed to handle " + typeName + " for transformation: " + throwable.getMessage()); } @Override public void onTransformation( final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module, final boolean loaded, final DynamicType dynamicType) { log.debug("Transformed {} -- {}", typeDescription, classLoader); } @Override public void onIgnored( final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {} @Override public void onComplete( final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {} @Override public void onDiscovery( final String typeName, final ClassLoader classLoader, final JavaModule module, final boolean loaded) {} } }