Merge pull request #310 from DataDog/tyler/jacoco

Apply jacoco to every java project
This commit is contained in:
Tyler Benson 2018-05-07 10:28:44 +10:00 committed by GitHub
commit e3aae4e869
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 322 additions and 229 deletions

View File

@ -53,7 +53,3 @@ tasks.withType(Test) {
parent.subprojects.collect { it.tasks.withType(Test) } each {
test.shouldRunAfter it
}
// Jacoco must be applied after the test javaagent config block above,
// otherwise the javaagent args conflict. (It's order dependent and added LIFO)
apply from: "${rootDir}/gradle/jacoco.gradle"

View File

@ -39,7 +39,7 @@ public class IntegrationTestUtils {
classloaderField = tracingAgentClass.getDeclaredField("AGENT_CLASSLOADER");
classloaderField.setAccessible(true);
return (ClassLoader) classloaderField.get(null);
} catch (Exception e) {
} catch (final Exception e) {
throw new IllegalStateException(e);
} finally {
if (null != classloaderField) {
@ -141,29 +141,19 @@ public class IntegrationTestUtils {
return className.replace('.', '/') + ".class";
}
public static String[] getBootstrapPackagePrefixes() {
try {
Field f =
getAgentClassLoader()
.loadClass("datadog.trace.agent.tooling.Utils")
.getField("BOOTSTRAP_PACKAGE_PREFIXES");
return (String[]) f.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
public static String[] getBootstrapPackagePrefixes() throws Exception {
final Field f =
getAgentClassLoader()
.loadClass("datadog.trace.agent.tooling.Utils")
.getField("BOOTSTRAP_PACKAGE_PREFIXES");
return (String[]) f.get(null);
}
public static String[] getAgentPackagePrefixes() {
try {
Field f =
getAgentClassLoader()
.loadClass("datadog.trace.agent.tooling.Utils")
.getField("AGENT_PACKAGE_PREFIXES");
return (String[]) f.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
public static String[] getAgentPackagePrefixes() throws Exception {
final Field f =
getAgentClassLoader()
.loadClass("datadog.trace.agent.tooling.Utils")
.getField("AGENT_PACKAGE_PREFIXES");
return (String[]) f.get(null);
}
}

View File

@ -5,6 +5,10 @@ plugins {
apply from: "${rootDir}/gradle/java.gradle"
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.trace.bootstrap.*'
]
dependencies {
compile project(':dd-trace-api')
compile deps.opentracing

View File

@ -1,7 +1,7 @@
package datadog.trace.bootstrap;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -11,36 +11,37 @@ import java.util.concurrent.atomic.AtomicInteger;
* #incrementCallDepth at the beginning of each constructor.
*/
public class CallDepthThreadLocalMap {
private static final ThreadLocal<Map<Object, CallDepthThreadLocalMap>> INSTANCES =
new ThreadLocal<>();
private static final ThreadLocal<Map<Key, AtomicInteger>> TLS =
new ThreadLocal<Map<Key, AtomicInteger>>() {
@Override
public Map<Key, AtomicInteger> initialValue() {
return new HashMap<>();
}
};
public static CallDepthThreadLocalMap get(Object o) {
if (INSTANCES.get() == null) {
INSTANCES.set(new WeakHashMap<Object, CallDepthThreadLocalMap>());
}
if (!INSTANCES.get().containsKey(o)) {
INSTANCES.get().put(o, new CallDepthThreadLocalMap());
}
return INSTANCES.get().get(o);
}
private final ThreadLocal<AtomicInteger> tls = new ThreadLocal<>();
private CallDepthThreadLocalMap() {}
public int incrementCallDepth() {
AtomicInteger depth = tls.get();
public static int incrementCallDepth(final Key k) {
final Map<Key, AtomicInteger> map = TLS.get();
AtomicInteger depth = map.get(k);
if (depth == null) {
depth = new AtomicInteger(0);
tls.set(depth);
map.put(k, depth);
return 0;
} else {
return depth.incrementAndGet();
}
}
public void reset() {
tls.remove();
INSTANCES.get().remove(this);
public static void reset(final Key k) {
final Map<Key, AtomicInteger> map = TLS.get();
if (map != null) {
map.remove(k);
}
}
public enum Key {
CLASSLOADER,
CONNECTION,
PREPARED_STATEMENT,
STATEMENT
}
}

View File

@ -0,0 +1,35 @@
package datadog.trace.bootstrap
import spock.lang.Specification
class CallDepthThreadLocalMapTest extends Specification {
def "test CallDepthThreadLocalMap"() {
setup:
def k1 = CallDepthThreadLocalMap.Key.CLASSLOADER
def k2 = CallDepthThreadLocalMap.Key.CONNECTION
expect:
CallDepthThreadLocalMap.incrementCallDepth(k1) == 0
CallDepthThreadLocalMap.incrementCallDepth(k2) == 0
CallDepthThreadLocalMap.incrementCallDepth(k1) == 1
CallDepthThreadLocalMap.incrementCallDepth(k2) == 1
when:
CallDepthThreadLocalMap.reset(k1)
then:
CallDepthThreadLocalMap.incrementCallDepth(k2) == 2
when:
CallDepthThreadLocalMap.reset(k2)
then:
CallDepthThreadLocalMap.incrementCallDepth(k1) == 0
CallDepthThreadLocalMap.incrementCallDepth(k2) == 0
CallDepthThreadLocalMap.incrementCallDepth(k1) == 1
CallDepthThreadLocalMap.incrementCallDepth(k2) == 1
}
}

View File

@ -1,10 +1,15 @@
apply from: "${rootDir}/gradle/java.gradle"
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.trace.agent.tooling.*'
]
dependencies {
compile project(':dd-java-agent:agent-bootstrap')
compile deps.bytebuddy
compile deps.bytebuddyagent
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compileOnly project(':dd-trace-ot')

View File

@ -18,7 +18,7 @@ public interface Instrumenter {
protected final boolean enabled;
public Configurable(final String instrumentationName, final String... additionalNames) {
this.instrumentationNames = new HashSet(Arrays.asList(additionalNames));
this.instrumentationNames = new HashSet<>(Arrays.asList(additionalNames));
instrumentationNames.add(instrumentationName);
// If default is enabled, we want to enable individually,

View File

@ -6,13 +6,8 @@ description = 'dd-java-agent'
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/publish.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
jacocoTestReport.dependsOn ':dd-java-agent-ittests:test'
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.agent.*',
'datadog.agent.decorators.*',
]
jacocoTestReport.dependsOn ':dd-java-agent-ittests:test'
/*
* Include subproject's shadowJar in the dd-java-agent jar.

View File

@ -31,4 +31,6 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
}

View File

@ -33,7 +33,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
// Include httpclient instrumentation for testing because it is a dependency for aws-sdk.

View File

@ -33,7 +33,7 @@ class SpanDecorator {
private static final Map<String, String> SERVICE_NAMES = new ConcurrentHashMap<>();
private static final Map<Class, String> OPERATION_NAMES = new ConcurrentHashMap<>();
static void onRequest(final Request request, final Span span) {
static void onRequest(final Request<?> request, final Span span) {
Tags.COMPONENT.set(span, COMPONENT_NAME);
Tags.HTTP_METHOD.set(span, request.getHttpMethod().name());
Tags.HTTP_URL.set(span, request.getEndpoint().toString());
@ -52,9 +52,9 @@ class SpanDecorator {
try {
final StringBuilder params = new StringBuilder("{");
final Map<String, List<Object>> requestParams = request.getParameters();
final Map<String, List<String>> requestParams = request.getParameters();
boolean firstKey = true;
for (final Entry<String, List<Object>> entry : requestParams.entrySet()) {
for (final Entry<String, List<String>> entry : requestParams.entrySet()) {
if (!firstKey) {
params.append(",");
}

View File

@ -6,7 +6,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
}

View File

@ -1,6 +1,7 @@
package datadog.trace.instrumentation.classloaders;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.bootstrap.CallDepthThreadLocalMap.Key.CLASSLOADER;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
@ -45,7 +46,7 @@ public final class ClassLoaderInstrumentation extends Instrumenter.Configurable
public static int constructorEnter() {
// We use this to make sure we only apply the exit instrumentation
// after the constructors are done calling their super constructors.
return CallDepthThreadLocalMap.get(ClassLoader.class).incrementCallDepth();
return CallDepthThreadLocalMap.incrementCallDepth(CLASSLOADER);
}
// Not sure why, but adding suppress causes a verify error.
@ -53,7 +54,7 @@ public final class ClassLoaderInstrumentation extends Instrumenter.Configurable
public static void constructorExit(
@Advice.This final ClassLoader cl, @Advice.Enter final int depth) {
if (depth == 0) {
CallDepthThreadLocalMap.get(ClassLoader.class).reset();
CallDepthThreadLocalMap.reset(CLASSLOADER);
try {
final Field field = GlobalTracer.class.getDeclaredField("tracer");

View File

@ -33,6 +33,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.2.0'

View File

@ -28,6 +28,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:java-concurrent')

View File

@ -35,6 +35,8 @@ class HystrixTest extends AgentTestRunner {
operation(command)
}
expect:
TRANSFORMED_CLASSES.contains("com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker")
TRANSFORMED_CLASSES.contains("HystrixTest\$1")
result == "Hello!"
assertTraces(TEST_WRITER, 1) {
@ -106,6 +108,8 @@ class HystrixTest extends AgentTestRunner {
operation(command)
}
expect:
TRANSFORMED_CLASSES.contains("com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker")
TRANSFORMED_CLASSES.contains("HystrixTest\$2")
result == "Fallback!"
assertTraces(TEST_WRITER, 1) {

View File

@ -15,6 +15,10 @@ subprojects { subProj ->
}
}
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.trace.instrumentation.*'
]
dependencies {
compile(project(':dd-java-agent:agent-tooling')) {
exclude module: ':dd-java-agent:agent-bootstrap'

View File

@ -1,6 +1,10 @@
apply from: "${rootDir}/gradle/java.gradle"
apply plugin: 'scala'
whitelistedInstructionClasses += whitelistedBranchClasses += [
'*'
]
dependencies {
compile project(':dd-trace-api')
compile project(':dd-trace-ot')

View File

@ -1,12 +1,11 @@
import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props}
import akka.pattern.ask
import akka.util.Timeout
import datadog.trace.api.Trace
import datadog.trace.context.TraceScope
import akka.pattern.ask
import io.opentracing.util.GlobalTracer
import scala.concurrent.duration._
import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props}
import akka.routing.Broadcast
import akka.util.Timeout
// ! == send-message
object AkkaActors {
@ -84,7 +83,6 @@ class Receiver extends Actor with ActorLogging {
def receive = {
case Greeting(greeting) => {
AkkaActors.tracedChild(greeting)
"done"
}
}

View File

@ -6,7 +6,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:trace-annotation')

View File

@ -16,7 +16,12 @@ import datadog.trace.context.TraceScope;
import io.opentracing.Scope;
import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Field;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
@ -78,8 +83,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
"akka.dispatch.ExecutionContexts$sameThreadExecutionContext$",
"play.api.libs.streams.Execution$trampoline$"
};
WHITELISTED_EXECUTORS =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(whitelist)));
WHITELISTED_EXECUTORS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(whitelist)));
}
public ExecutorInstrumentation() {
@ -93,7 +97,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
.and(
new ElementMatcher<TypeDescription>() {
@Override
public boolean matches(TypeDescription target) {
public boolean matches(final TypeDescription target) {
final boolean whitelisted = WHITELISTED_EXECUTORS.contains(target.getName());
if (!whitelisted) {
log.debug("Skipping executor instrumentation for {}", target.getName());
@ -157,13 +161,13 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
public static class WrapCallableAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static DatadogWrapper wrapJob(
@Advice.Argument(value = 0, readOnly = false) Callable task) {
@Advice.Argument(value = 0, readOnly = false) Callable<?> task) {
final Scope scope = GlobalTracer.get().scopeManager().active();
if (scope instanceof TraceScope
&& ((TraceScope) scope).isAsyncPropagating()
&& task != null
&& !(task instanceof DatadogWrapper)) {
task = new CallableWrapper(task, (TraceScope) scope);
task = new CallableWrapper<>(task, (TraceScope) scope);
return (CallableWrapper) task;
}
return null;
@ -184,11 +188,11 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
@Advice.Argument(value = 0, readOnly = false) Collection<? extends Callable<?>> tasks) {
final Scope scope = GlobalTracer.get().scopeManager().active();
if (scope instanceof TraceScope && ((TraceScope) scope).isAsyncPropagating()) {
Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size());
for (Callable task : tasks) {
final Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size());
for (Callable<?> task : tasks) {
if (task != null) {
if (!(task instanceof CallableWrapper)) {
task = new CallableWrapper(task, (TraceScope) scope);
task = new CallableWrapper<>(task, (TraceScope) scope);
}
wrappedTasks.add(task);
}
@ -203,7 +207,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
public static void checkCancel(
@Advice.Enter final Collection<?> wrappedJobs, @Advice.Thrown final Throwable throwable) {
if (null != wrappedJobs && null != throwable) {
for (Object wrapper : wrappedJobs) {
for (final Object wrapper : wrappedJobs) {
if (wrapper instanceof DatadogWrapper) {
((DatadogWrapper) wrapper).cancel();
}
@ -217,7 +221,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
public abstract static class DatadogWrapper {
protected final TraceScope.Continuation continuation;
public DatadogWrapper(TraceScope scope) {
public DatadogWrapper(final TraceScope scope) {
continuation = scope.capture();
log.debug("created continuation {} from scope {}", continuation, scope);
}
@ -234,7 +238,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
public static class RunnableWrapper extends DatadogWrapper implements Runnable {
private final Runnable delegatee;
public RunnableWrapper(Runnable toWrap, TraceScope scope) {
public RunnableWrapper(final Runnable toWrap, final TraceScope scope) {
super(scope);
delegatee = toWrap;
}
@ -255,7 +259,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
public static class CallableWrapper<T> extends DatadogWrapper implements Callable<T> {
private final Callable<T> delegatee;
public CallableWrapper(Callable<T> toWrap, TraceScope scope) {
public CallableWrapper(final Callable<T> toWrap, final TraceScope scope) {
super(scope);
delegatee = toWrap;
}
@ -274,14 +278,14 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
/** Utils for pulling DatadogWrapper out of Future instances. */
public static class ConcurrentUtils {
private static Map<Class<?>, Field> fieldCache = new ConcurrentHashMap<>();
private static String[] wrapperFields = {"runnable", "callable"};
private static final Map<Class<?>, Field> fieldCache = new ConcurrentHashMap<>();
private static final String[] wrapperFields = {"runnable", "callable"};
public static boolean safeToWrap(Future<?> f) {
public static boolean safeToWrap(final Future<?> f) {
return null != getDatadogWrapper(f);
}
public static DatadogWrapper getDatadogWrapper(Future<?> f) {
public static DatadogWrapper getDatadogWrapper(final Future<?> f) {
final Field field;
if (fieldCache.containsKey(f.getClass())) {
field = fieldCache.get(f.getClass());
@ -293,7 +297,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
if (field != null) {
try {
field.setAccessible(true);
Object o = field.get(f);
final Object o = field.get(f);
if (o instanceof DatadogWrapper) {
return (DatadogWrapper) o;
}
@ -312,7 +316,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
try {
field = clazz.getDeclaredField(wrapperFields[i]);
break;
} catch (Exception e) {
} catch (final Exception e) {
}
}
clazz = clazz.getSuperclass();

View File

@ -13,7 +13,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compile project(':dd-java-agent:agent-tooling')

View File

@ -18,7 +18,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compile project(':dd-java-agent:agent-tooling')

View File

@ -3,7 +3,8 @@ apply from: "${rootDir}/gradle/java.gradle"
dependencies {
compile project(':dd-java-agent:agent-tooling')
compile deps.bytebuddy
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile group: 'org.jboss.modules', name: 'jboss-modules', version: '1.3.10.Final'
testCompile project(':dd-java-agent:testing')

View File

@ -5,5 +5,6 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
}

View File

@ -1,5 +1,6 @@
package datadog.trace.instrumentation.jdbc;
import static datadog.trace.bootstrap.CallDepthThreadLocalMap.Key.CONNECTION;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
@ -58,7 +59,7 @@ public final class ConnectionInstrumentation extends Instrumenter.Configurable {
public static int constructorEnter() {
// We use this to make sure we only apply the exit instrumentation
// after the constructors are done calling their super constructors.
return CallDepthThreadLocalMap.get(Connection.class).incrementCallDepth();
return CallDepthThreadLocalMap.incrementCallDepth(CONNECTION);
}
// Since we're instrumenting the constructor, we can't add onThrowable.
@ -67,12 +68,12 @@ public final class ConnectionInstrumentation extends Instrumenter.Configurable {
@Advice.Enter final int depth, @Advice.This final Connection connection)
throws SQLException {
if (depth == 0) {
CallDepthThreadLocalMap.get(Connection.class).reset();
CallDepthThreadLocalMap.reset(CONNECTION);
final String url = connection.getMetaData().getURL();
if (url != null) {
// Remove end of url to prevent passwords from leaking:
final String sanitizedURL = url.replaceAll("[?;].*", "");
final String type = url.split(":")[1];
final String type = url.split(":", -1)[1];
String user = connection.getMetaData().getUserName();
if (user != null && user.trim().equals("")) {
user = null;

View File

@ -1,5 +1,6 @@
package datadog.trace.instrumentation.jdbc;
import static datadog.trace.bootstrap.CallDepthThreadLocalMap.Key.PREPARED_STATEMENT;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
@ -51,8 +52,7 @@ public final class PreparedStatementInstrumentation extends Instrumenter.Configu
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope startSpan(@Advice.This final PreparedStatement statement) {
final int callDepth =
CallDepthThreadLocalMap.get(PreparedStatement.class).incrementCallDepth();
final int callDepth = CallDepthThreadLocalMap.incrementCallDepth(PREPARED_STATEMENT);
if (callDepth > 0) {
return null;
}
@ -99,7 +99,7 @@ public final class PreparedStatementInstrumentation extends Instrumenter.Configu
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
}
scope.close();
CallDepthThreadLocalMap.get(PreparedStatement.class).reset();
CallDepthThreadLocalMap.reset(PREPARED_STATEMENT);
}
}
}

View File

@ -1,5 +1,6 @@
package datadog.trace.instrumentation.jdbc;
import static datadog.trace.bootstrap.CallDepthThreadLocalMap.Key.STATEMENT;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
@ -52,7 +53,7 @@ public final class StatementInstrumentation extends Instrumenter.Configurable {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope startSpan(
@Advice.Argument(0) final String sql, @Advice.This final Statement statement) {
final int callDepth = CallDepthThreadLocalMap.get(Statement.class).incrementCallDepth();
final int callDepth = CallDepthThreadLocalMap.incrementCallDepth(STATEMENT);
if (callDepth > 0) {
return null;
}
@ -100,7 +101,7 @@ public final class StatementInstrumentation extends Instrumenter.Configurable {
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
}
scope.close();
CallDepthThreadLocalMap.get(Statement.class).reset();
CallDepthThreadLocalMap.reset(STATEMENT);
}
}
}

View File

@ -27,7 +27,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6'

View File

@ -27,7 +27,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '8.0.0.v20110901'

View File

@ -18,7 +18,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compile project(':dd-java-agent:agent-tooling')

View File

@ -22,7 +22,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compile project(':dd-java-agent:agent-tooling')

View File

@ -27,6 +27,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'org.apache.kafka', name: 'kafka-clients', version: '0.11.0.0'

View File

@ -72,7 +72,7 @@ public final class KafkaConsumerInstrumentation extends Instrumenter.Configurabl
@Advice.OnMethodExit(suppress = Throwable.class)
public static void wrap(@Advice.Return(readOnly = false) Iterable<ConsumerRecord> iterable) {
if (iterable != null) {
iterable = new TracingIterable(iterable, "kafka.consume", ConsumeScopeAction.INSTANCE);
iterable = new TracingIterable<>(iterable, "kafka.consume", ConsumeScopeAction.INSTANCE);
}
}
}
@ -83,7 +83,7 @@ public final class KafkaConsumerInstrumentation extends Instrumenter.Configurabl
public static void wrap(@Advice.Return(readOnly = false) Iterator<ConsumerRecord> iterator) {
if (iterator != null) {
iterator =
new TracingIterable.TracingIterator(
new TracingIterable.TracingIterator<>(
iterator, "kafka.consume", ConsumeScopeAction.INSTANCE);
}
}

View File

@ -67,9 +67,10 @@ public class TracingIterable<T> implements Iterable<T> {
decorator.decorate(spanBuilder, next);
currentScope = spanBuilder.startActive(true);
}
} finally {
return next;
} catch (final Exception e) {
log.debug("Error during decoration", e);
}
return next;
}
@Override

View File

@ -27,6 +27,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
// Include kafka-clients instrumentation for tests.

View File

@ -27,6 +27,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-trace-ot')
testCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.4.2'

View File

@ -23,4 +23,6 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
}

View File

@ -32,6 +32,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0'

View File

@ -3,7 +3,8 @@ apply from: "${rootDir}/gradle/java.gradle"
dependencies {
compile project(':dd-java-agent:agent-tooling')
compile deps.bytebuddy
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile group: 'org.osgi', name: 'org.osgi.core', version: '4.0.0'
testCompile project(':dd-java-agent:testing')

View File

@ -14,7 +14,8 @@ dependencies {
compile project(':dd-java-agent:agent-tooling')
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile group: 'org.scala-lang', name: 'scala-library', version: '2.11.12'
testCompile group: 'com.typesafe.play', name: 'play_2.11', version: '2.4.0'

View File

@ -26,6 +26,10 @@ compileMain_java8Java {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
configurations {
main_java8AnnotationProcessor.extendsFrom lombok
main_java8Implementation.extendsFrom lombok
}
apply plugin: 'org.unbroken-dome.test-sets'
@ -43,7 +47,9 @@ dependencies {
main_java8Compile deps.bytebuddy
main_java8Compile deps.opentracing
main_java8Compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compileOnly sourceSets.main_java8.compileClasspath

View File

@ -19,7 +19,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'org.eclipse.jetty', name: 'jetty-server', version: '7.0.0.v20091005'

View File

@ -38,14 +38,14 @@ public class HttpServletRequestExtractAdapter implements TextMap {
final HttpServletRequest httpServletRequest) {
final Map<String, List<String>> headersResult = new HashMap<>();
final Enumeration<String> headerNamesIt = httpServletRequest.getHeaderNames();
final Enumeration<?> headerNamesIt = httpServletRequest.getHeaderNames();
while (headerNamesIt.hasMoreElements()) {
final String headerName = headerNamesIt.nextElement();
final String headerName = headerNamesIt.nextElement().toString();
final Enumeration<String> valuesIt = httpServletRequest.getHeaders(headerName);
final Enumeration<?> valuesIt = httpServletRequest.getHeaders(headerName);
final List<String> valuesList = new ArrayList<>(1);
while (valuesIt.hasMoreElements()) {
valuesList.add(valuesIt.nextElement());
valuesList.add(valuesIt.nextElement().toString());
}
headersResult.put(headerName, valuesList);

View File

@ -29,7 +29,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:jetty-8') // See if there's any conflicts.

View File

@ -42,7 +42,8 @@ dependencies {
compile project(':dd-java-agent:agent-tooling')
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:instrumentation:jetty-8')
testCompile project(':dd-java-agent:testing')

View File

@ -23,7 +23,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')

View File

@ -6,7 +6,8 @@ dependencies {
compile deps.bytebuddy
compile deps.opentracing
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
}

View File

@ -2,6 +2,7 @@ package datadog.trace.agent.test;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import com.google.common.collect.Sets;
import datadog.opentracing.DDSpan;
import datadog.opentracing.DDTracer;
import datadog.trace.agent.tooling.AgentInstaller;
@ -12,6 +13,8 @@ import io.opentracing.Tracer;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.Phaser;
import java.util.concurrent.atomic.AtomicInteger;
import net.bytebuddy.agent.ByteBuddyAgent;
@ -57,6 +60,8 @@ public abstract class AgentTestRunner extends Specification {
// loads opentracing before bootstrap classpath is setup
// so we declare tracer as an object and cast when needed.
protected static final Object TEST_TRACER;
protected static final Set<String> TRANSFORMED_CLASSES = Sets.newConcurrentHashSet();
private static final AtomicInteger INSTRUMENTATION_ERROR_COUNT = new AtomicInteger();
private static final Instrumentation instrumentation;
@ -101,6 +106,7 @@ public abstract class AgentTestRunner extends Specification {
final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(AgentTestRunner.class.getClassLoader());
assert ServiceLoader.load(Instrumenter.class).iterator().hasNext();
activeTransformer =
AgentInstaller.installBytebuddyAgent(instrumentation, new ErrorCountingListener());
} finally {
@ -142,7 +148,9 @@ public abstract class AgentTestRunner extends Specification {
final ClassLoader classLoader,
final JavaModule module,
final boolean loaded,
final DynamicType dynamicType) {}
final DynamicType dynamicType) {
TRANSFORMED_CLASSES.add(typeDescription.getActualName());
}
@Override
public void onIgnored(

View File

@ -1,5 +1,13 @@
apply from: "${rootDir}/gradle/java.gradle"
minimumBranchCoverage = 0.5
minimumInstructionCoverage = 0.6
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.trace.agent.test.*Assert',
'datadog.trace.agent.test.AgentTestRunner.1',
'datadog.trace.agent.test.TestUtils'
]
dependencies {
compile deps.bytebuddy
compile deps.bytebuddyagent
@ -7,9 +15,13 @@ dependencies {
compile deps.opentracing
compile deps.spock
compile deps.testLogging
compile deps.guava
compile project(':dd-trace-ot')
compile project(':dd-java-agent:agent-tooling')
annotationProcessor deps.autoservice
implementation deps.autoservice
compile deps.groovy

View File

@ -1,6 +1,5 @@
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/publish.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
description = 'dd-trace-api'
dependencies {

View File

@ -3,9 +3,9 @@ buildscript {
jcenter()
}
dependencies {
classpath "io.franzbecker:gradle-lombok:1.8"
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.4.18"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3"
classpath "io.franzbecker:gradle-lombok:1.13"
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.7.2"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0"
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
classpath 'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.5'
}

View File

@ -6,15 +6,12 @@ description = 'dd-trace-ot'
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/publish.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
minimumBranchCoverage = 0.3
minimumInstructionCoverage = 0.5
minimumBranchCoverage = 0.5
minimumInstructionCoverage = 0.6
whitelistedInstructionClasses += whitelistedBranchClasses += [
'datadog.opentracing.decorators.*',
'datadog.trace.common.writer.ListWriter',
'datadog.trace.common.util.Clock',
'datadog.trace.api.DDTags',
'datadog.trace.common.util.ConfigUtils',
'datadog.trace.common.sampling.PrioritySampling'
]
@ -28,7 +25,8 @@ testSets {
}
dependencies {
compile deps.autoservice
annotationProcessor deps.autoservice
implementation deps.autoservice
compile project(':dd-trace-api')
compile deps.opentracing

View File

@ -2,6 +2,7 @@ package datadog.opentracing.decorators;
import datadog.opentracing.DDSpanContext;
import io.opentracing.tag.Tags;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -11,18 +12,19 @@ import java.util.Map;
*/
public class OperationDecorator extends AbstractDecorator {
static final Map<String, String> MAPPINGS =
new HashMap<String, String>() {
{
// Component name <> Operation name
put("apache-httpclient", "apache.http");
put("java-aws-sdk", "aws.http");
// FIXME: JMS ops card is low (jms-send or jms-receive), may be this mapping is useless
put("java-jms", "jms");
put("okhttp", "okhttp.http");
// Cassandra, Mongo, JDBC are set via DBTypeDecorator
}
};
static final Map<String, String> MAPPINGS;
static {
final Map<String, String> mappings = new HashMap<>();
// Component name <> Operation name
mappings.put("apache-httpclient", "apache.http");
mappings.put("java-aws-sdk", "aws.http");
// FIXME: JMS ops card is low (jms-send or jms-receive), may be this mapping is useless
mappings.put("java-jms", "jms");
mappings.put("okhttp", "okhttp.http");
// Cassandra, Mongo, JDBC are set via DBTypeDecorator
MAPPINGS = Collections.unmodifiableMap(mappings);
}
public OperationDecorator() {
super();

View File

@ -8,7 +8,7 @@ import java.util.Deque;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ContextualScopeManager implements ScopeManager {
final ThreadLocal<Scope> tlsScope = new ThreadLocal<>();
static final ThreadLocal<Scope> tlsScope = new ThreadLocal<>();
final Deque<ScopeContext> scopeContexts = new ConcurrentLinkedDeque<>();
@Override

View File

@ -78,7 +78,7 @@ public class ContinuableScope implements Scope, TraceScope {
}
@Override
public void setAsyncPropagation(boolean value) {
public void setAsyncPropagation(final boolean value) {
isAsyncPropagating.set(value);
}
@ -87,6 +87,7 @@ public class ContinuableScope implements Scope, TraceScope {
*
* @return The new continuation, or null if this scope is not async propagating.
*/
@Override
public Continuation capture() {
if (isAsyncPropagating()) {
return new Continuation();
@ -108,6 +109,7 @@ public class ContinuableScope implements Scope, TraceScope {
trace.registerContinuation(this);
}
@Override
public ContinuableScope activate() {
if (used.compareAndSet(false, true)) {
return new ContinuableScope(scopeManager, openCount, this, spanUnderScope, finishOnClose);

View File

@ -83,12 +83,14 @@ public class DDTraceConfig extends Properties {
return Collections.emptyMap();
}
final String[] tokens = str.split(",");
final String[] tokens = str.split(",", -1);
final Map<String, Object> map = new HashMap<>(tokens.length + 1, 1f);
for (final String token : tokens) {
final String[] keyValue = token.split(":");
map.put(keyValue[0].trim(), keyValue[1].trim());
final String[] keyValue = token.split(":", -1);
if (keyValue.length == 2) {
map.put(keyValue[0].trim(), keyValue[1].trim());
}
}
return Collections.unmodifiableMap(map);
}

View File

@ -1,64 +0,0 @@
package datadog.trace.common;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
public class Service {
private final String name;
private final String appName;
private final Service.AppType appType;
public Service(final String name, final String appName, final AppType appType) {
this.name = name;
this.appName = appName;
this.appType = appType;
}
@JsonIgnore
public String getName() {
return name;
}
@JsonProperty("app")
public String getAppName() {
return appName;
}
@JsonProperty("app_type")
public AppType getAppType() {
return appType;
}
@Override
public String toString() {
return "Service { "
+ "name='"
+ name
+ "\', appName='"
+ appName
+ "', appType="
+ appType
+ " }";
}
public enum AppType {
WEB("web"),
DB("db"),
CUSTOM("custom"),
CACHE("cache"),
WORKER("worker");
private final String type;
AppType(final String type) {
this.type = type;
}
@JsonValue
public String toString() {
return type;
}
}
}

View File

@ -10,6 +10,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -82,7 +83,8 @@ public class DDApi {
String responseString = null;
{
final BufferedReader responseReader =
new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
new BufferedReader(
new InputStreamReader(httpCon.getInputStream(), StandardCharsets.UTF_8));
final StringBuilder sb = new StringBuilder();
String line = null;

View File

@ -1,7 +1,7 @@
package datadog.trace.common.writer;
import datadog.opentracing.DDSpan;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
@ -10,7 +10,7 @@ import java.util.concurrent.TimeoutException;
/** List writer used by tests mostly */
public class ListWriter extends CopyOnWriteArrayList<List<DDSpan>> implements Writer {
private final List<CountDownLatch> latches = new LinkedList<>();
private final List<CountDownLatch> latches = new ArrayList<>();
public List<DDSpan> firstTrace() {
return get(0);

View File

@ -7,6 +7,7 @@ import datadog.opentracing.PendingTrace
import datadog.trace.common.writer.ListWriter
import io.opentracing.Scope
import io.opentracing.Span
import io.opentracing.noop.NoopSpan
import spock.lang.Specification
import spock.lang.Subject
import spock.lang.Unroll
@ -25,6 +26,21 @@ class ScopeManagerTest extends Specification {
scopeManager.tlsScope.remove()
}
def "non-ddspan activation results in a simple scope"() {
when:
def scope = scopeManager.activate(NoopSpan.INSTANCE, true)
then:
scopeManager.active() == scope
scope instanceof SimpleScope
when:
scope.close()
then:
scopeManager.active() == null
}
def "threadlocal is empty"() {
setup:
def builder = tracer.buildSpan("test")

View File

@ -8,6 +8,25 @@ import spock.lang.Specification
class RateByServiceSamplerTest extends Specification {
def "invalid rate -> 1"() {
setup:
RateByServiceSampler serviceSampler = new RateByServiceSampler()
ObjectMapper serializer = new ObjectMapper()
String response = '{"rate_by_service": {"service:,env:":' + rate + '}}'
serviceSampler.onResponse("traces", serializer.readTree(response))
expect:
serviceSampler.baseSampler.sampleRate == expectedRate
where:
rate | expectedRate
null | 1
1 | 1
0 | 1
-5 | 1
5 | 1
0.5 | 0.5
}
def "rate by service name"() {
setup:
RateByServiceSampler serviceSampler = new RateByServiceSampler()

View File

@ -4,7 +4,6 @@ plugins {
apply plugin: 'application'
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
version = 'demo'
description = 'dropwizard-mongo-client'

View File

@ -7,12 +7,12 @@ public class Book {
private final String title;
private final int numberPages;
private final String IsbnCode;
private final String isbnCode;
public Book(final String isbnCode, final String title, final int numberPages) {
this.title = title;
this.numberPages = numberPages;
IsbnCode = isbnCode;
this.isbnCode = isbnCode;
}
public Book(final Document d) {
@ -21,7 +21,7 @@ public class Book {
@JsonProperty("ISBN")
public String getIsbnCode() {
return IsbnCode;
return isbnCode;
}
public String getTitle() {
@ -33,6 +33,6 @@ public class Book {
}
public Document toDocument() {
return new Document("isbn", IsbnCode).append("title", title).append("page", numberPages);
return new Document("isbn", isbnCode).append("title", title).append("page", numberPages);
}
}

View File

@ -4,7 +4,6 @@ plugins {
apply plugin: 'application'
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
version = 'demo'
description = 'rest-spark'

View File

@ -3,7 +3,6 @@ plugins {
}
apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/jacoco.gradle"
version = 'demo'
description = 'spring-boot-jdbc-redis'

View File

@ -1,5 +1,9 @@
apply plugin: "jacoco"
jacoco {
toolVersion = "0.8.0"
}
jacocoTestReport {
dependsOn test
reports {
@ -9,11 +13,21 @@ jacocoTestReport {
}
}
project.ext.whitelistedBranchClasses = []
project.ext.whitelistedInstructionClasses = []
if (project.parent.hasProperty("whitelistedBranchClasses")) {
project.ext.whitelistedBranchClasses = parent.whitelistedBranchClasses
} else {
project.ext.whitelistedBranchClasses = []
}
project.ext.minimumBranchCoverage = 0.6
project.ext.minimumInstructionCoverage = 0.6
if (project.parent.hasProperty("whitelistedInstructionClasses")) {
project.ext.whitelistedInstructionClasses = parent.whitelistedInstructionClasses
} else {
project.ext.whitelistedInstructionClasses = []
}
// defaults can be overridden per project:
project.ext.minimumBranchCoverage = 0.9
project.ext.minimumInstructionCoverage = 0.9
afterEvaluate {
jacocoTestCoverageVerification {

View File

@ -13,6 +13,7 @@ lombok { // optional: values below are the defaults
apply plugin: "net.ltgt.errorprone"
tasks.withType(JavaCompile) {
options.compilerArgs += ['-Xep:FutureReturnValueIgnored:OFF']
// workaround for: https://github.com/google/error-prone/issues/780
options.compilerArgs += ['-Xep:ParameterName:OFF']
}
@ -152,6 +153,7 @@ tasks.withType(Test) {
apply from: "$rootDir/gradle/checkstyle.gradle"
apply from: "$rootDir/gradle/codenarc.gradle"
apply from: "$rootDir/gradle/jacoco.gradle"
plugins.withType(BasePlugin) {
project.afterEvaluate {