add version scan and rename instrumentation classes

This commit is contained in:
Gary Huang 2018-06-04 17:39:58 -04:00 committed by Gary Huang
parent 3d61d839c8
commit b694ecdf79
16 changed files with 123 additions and 107 deletions

View File

@ -1,3 +1,15 @@
apply plugin: 'version-scan'
versionScan {
group = "io.lettuce"
module = "lettuce-core"
versions = "[5.0.0.RELEASE,)"
scanDependencies = true
verifyPresent = [
"io.lettuce.core.RedisClient": null,
]
}
apply from: "${rootDir}/gradle/java.gradle"
sourceSets {

View File

@ -1,5 +1,6 @@
package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*;
import com.google.auto.service.AutoService;
@ -10,16 +11,17 @@ import datadog.trace.agent.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable {
public class LettuceAsyncCommandsInstrumentation extends Instrumenter.Configurable {
private static final HelperInjector REDIS_ASYNC_HELPERS =
new HelperInjector(
RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction",
RedisAsyncCommandsInstrumentation.class.getPackage().getName()
LettuceAsyncCommandsInstrumentation.class.getPackage().getName()
+ ".LettuceAsyncBiFunction",
LettuceAsyncCommandsInstrumentation.class.getPackage().getName()
+ ".LettuceInstrumentationUtil");
public RedisAsyncCommandsInstrumentation() {
super("redis");
public LettuceAsyncCommandsInstrumentation() {
super("lettuce", "lettuce-5-async");
}
@Override
@ -30,7 +32,9 @@ public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable
@Override
protected AgentBuilder apply(AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.lettuce.core.AbstractRedisAsyncCommands"))
.type(
named("io.lettuce.core.AbstractRedisAsyncCommands"),
classLoaderHasClasses("io.lettuce.core.RedisClient"))
.transform(REDIS_ASYNC_HELPERS)
.transform(DDTransformers.defaultTransformers())
.transform(
@ -39,7 +43,7 @@ public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable
isMethod()
.and(named("dispatch"))
.and(takesArgument(0, named("io.lettuce.core.protocol.RedisCommand"))),
RedisAsyncCommandsAdvice.class.getName()))
LettuceAsyncCommandsAdvice.class.getName()))
.asDecorator();
}
}

View File

@ -1,5 +1,6 @@
package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*;
import com.google.auto.service.AutoService;
@ -10,14 +11,16 @@ import datadog.trace.agent.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public final class RedisClientInstrumentation extends Instrumenter.Configurable {
public final class LettuceClientInstrumentation extends Instrumenter.Configurable {
private static final HelperInjector REDIS_ASYNC_HELPERS =
new HelperInjector(
RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction");
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".LettuceInstrumentationUtil",
LettuceClientInstrumentation.class.getPackage().getName() + ".LettuceAsyncBiFunction");
public RedisClientInstrumentation() {
super("redis");
public LettuceClientInstrumentation() {
super("lettuce");
}
@Override
@ -28,7 +31,9 @@ public final class RedisClientInstrumentation extends Instrumenter.Configurable
@Override
public AgentBuilder apply(final AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.lettuce.core.RedisClient"))
.type(
named("io.lettuce.core.RedisClient"),
classLoaderHasClasses("io.lettuce.core.RedisClient"))
.transform(DDTransformers.defaultTransformers())
.transform(REDIS_ASYNC_HELPERS)
.transform(

View File

@ -0,0 +1,67 @@
package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.DDAdvice;
import datadog.trace.agent.tooling.DDTransformers;
import datadog.trace.agent.tooling.HelperInjector;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.instrumentation.lettuce.rx.LettuceFluxCreationAdvice;
import datadog.trace.instrumentation.lettuce.rx.LettuceMonoCreationAdvice;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class LettuceReactiveCommandsInstrumentation extends Instrumenter.Configurable {
private static final HelperInjector REDIS_RX_HELPERS =
new HelperInjector(
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".LettuceInstrumentationUtil",
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.LettuceMonoCreationAdvice",
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.LettuceMonoDualConsumer",
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.LettuceFluxCreationAdvice",
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.LettuceFluxTerminationRunnable",
LettuceReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.LettuceFluxTerminationRunnable$FluxOnSubscribeConsumer");
public LettuceReactiveCommandsInstrumentation() {
super("lettuce", "lettuce-5-rx");
}
@Override
protected boolean defaultEnabled() {
return false;
}
@Override
protected AgentBuilder apply(AgentBuilder agentBuilder) {
return agentBuilder
.type(
named("io.lettuce.core.AbstractRedisReactiveCommands"),
classLoaderHasClasses("io.lettuce.core.RedisClient"))
.transform(REDIS_RX_HELPERS)
.transform(DDTransformers.defaultTransformers())
.transform(
DDAdvice.create()
.advice(
isMethod()
.and(named("createMono"))
.and(takesArgument(0, named("java.util.function.Supplier")))
.and(returns(named("reactor.core.publisher.Mono"))),
LettuceMonoCreationAdvice.class.getName())
.advice(
isMethod()
.and(nameStartsWith("create"))
.and(nameEndsWith("Flux"))
.and(takesArgument(0, named("java.util.function.Supplier")))
.and(returns(named(("reactor.core.publisher.Flux")))),
LettuceFluxCreationAdvice.class.getName()))
.asDecorator();
}
}

View File

@ -1,64 +0,0 @@
package datadog.trace.instrumentation.lettuce;
import static net.bytebuddy.matcher.ElementMatchers.*;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.DDAdvice;
import datadog.trace.agent.tooling.DDTransformers;
import datadog.trace.agent.tooling.HelperInjector;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.instrumentation.lettuce.rx.FluxCreationAdvice;
import datadog.trace.instrumentation.lettuce.rx.MonoCreationAdvice;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class RedisReactiveCommandsInstrumentation extends Instrumenter.Configurable {
private static final HelperInjector REDIS_ASYNC_HELPERS =
new HelperInjector(
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".LettuceInstrumentationUtil",
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.MonoCreationAdvice",
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.MonoDualConsumer",
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.FluxCreationAdvice",
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.FluxTerminationCancellableRunnable",
RedisReactiveCommandsInstrumentation.class.getPackage().getName()
+ ".rx.FluxTerminationCancellableRunnable$FluxOnSubscribeConsumer");
public RedisReactiveCommandsInstrumentation() {
super("redis");
}
@Override
protected boolean defaultEnabled() {
return false;
}
@Override
protected AgentBuilder apply(AgentBuilder agentBuilder) {
return agentBuilder
.type(named("io.lettuce.core.AbstractRedisReactiveCommands"))
.transform(REDIS_ASYNC_HELPERS)
.transform(DDTransformers.defaultTransformers())
.transform(
DDAdvice.create()
.advice(
isMethod()
.and(named("createMono"))
.and(takesArgument(0, named("java.util.function.Supplier")))
.and(returns(named("reactor.core.publisher.Mono"))),
MonoCreationAdvice.class.getName())
.advice(
isMethod()
.and(nameStartsWith("create"))
.and(nameEndsWith("Flux"))
.and(takesArgument(0, named("java.util.function.Supplier")))
.and(returns(named(("reactor.core.publisher.Flux")))),
FluxCreationAdvice.class.getName()))
.asDecorator();
}
}

View File

@ -54,7 +54,7 @@ public class ConnectionFutureAdvice {
}
// close spans on error or normal completion
connectionFuture.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
connectionFuture.handleAsync(new LettuceAsyncBiFunction<>(scope.span()));
scope.close();
}
}

View File

@ -15,12 +15,12 @@ import java.util.function.BiFunction;
* @param <R> the return type, should be null since nothing else should happen from tracing
* standpoint after the span is closed
*/
public class RedisAsyncBiFunction<T extends Object, U extends Throwable, R extends Object>
public class LettuceAsyncBiFunction<T extends Object, U extends Throwable, R extends Object>
implements BiFunction<T, Throwable, R> {
private final Span span;
public RedisAsyncBiFunction(Span span) {
public LettuceAsyncBiFunction(Span span) {
this.span = span;
}

View File

@ -11,7 +11,7 @@ import java.util.Collections;
import java.util.Map;
import net.bytebuddy.asm.Advice;
public class RedisAsyncCommandsAdvice {
public class LettuceAsyncCommandsAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope startSpan(@Advice.Argument(0) final RedisCommand command) {
@ -54,7 +54,7 @@ public class RedisAsyncCommandsAdvice {
}
// close spans on error or normal completion
asyncCommand.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
asyncCommand.handleAsync(new LettuceAsyncBiFunction<>(scope.span()));
scope.close();
}
}

View File

@ -7,7 +7,7 @@ import java.util.function.Supplier;
import net.bytebuddy.asm.Advice;
import reactor.core.publisher.Flux;
public class FluxCreationAdvice {
public class LettuceFluxCreationAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Map<String, String> extractCommand(
@ -21,8 +21,8 @@ public class FluxCreationAdvice {
@Advice.Return(readOnly = false) Flux<?> publisher) {
boolean finishSpanOnClose = LettuceInstrumentationUtil.doFinishSpanEarly(commandMap);
FluxTerminationCancellableRunnable handler =
new FluxTerminationCancellableRunnable(commandMap, finishSpanOnClose);
LettuceFluxTerminationRunnable handler =
new LettuceFluxTerminationRunnable(commandMap, finishSpanOnClose);
publisher = publisher.doOnSubscribe(handler.getOnSubscribeConsumer());
// don't register extra callbacks to finish the spans if the command being instrumented is one of those that return
// Mono<Void> (In here a flux is created first and then converted to Mono<Void>)

View File

@ -15,14 +15,13 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Signal;
import reactor.core.publisher.SignalType;
public class FluxTerminationCancellableRunnable implements Consumer<Signal>, Runnable {
public class LettuceFluxTerminationRunnable implements Consumer<Signal>, Runnable {
private Span span = null;
private int numResults = 0;
private FluxOnSubscribeConsumer onSubscribeConsumer = null;
public FluxTerminationCancellableRunnable(
Map<String, String> commandMap, boolean finishSpanOnClose) {
public LettuceFluxTerminationRunnable(Map<String, String> commandMap, boolean finishSpanOnClose) {
this.onSubscribeConsumer = new FluxOnSubscribeConsumer(this, commandMap, finishSpanOnClose);
}
@ -44,7 +43,7 @@ public class FluxTerminationCancellableRunnable implements Consumer<Signal>, Run
} else {
LoggerFactory.getLogger(Flux.class)
.error(
"Failed to finish this.span, FluxTerminationCancellableRunnable cannot find this.span because "
"Failed to finish this.span, LettuceFluxTerminationRunnable cannot find this.span because "
+ "it probably wasn't started.");
}
}
@ -66,19 +65,19 @@ public class FluxTerminationCancellableRunnable implements Consumer<Signal>, Run
} else {
LoggerFactory.getLogger(Flux.class)
.error(
"Failed to finish this.span to indicate cancellation, FluxTerminationCancellableRunnable cannot find this.span because "
"Failed to finish this.span to indicate cancellation, LettuceFluxTerminationRunnable cannot find this.span because "
+ "it probably wasn't started.");
}
}
public static class FluxOnSubscribeConsumer implements Consumer<Subscription> {
private final FluxTerminationCancellableRunnable owner;
private final LettuceFluxTerminationRunnable owner;
private final Map<String, String> commandMap;
private final boolean finishSpanOnClose;
public FluxOnSubscribeConsumer(
FluxTerminationCancellableRunnable owner,
LettuceFluxTerminationRunnable owner,
Map<String, String> commandMap,
boolean finishSpanOnClose) {
this.owner = owner;

View File

@ -7,10 +7,7 @@ import java.util.function.Supplier;
import net.bytebuddy.asm.Advice;
import reactor.core.publisher.Mono;
public class MonoCreationAdvice {
public static final String MAP_KEY_CMD_NAME = "CMD_NAME";
public static final String MAP_KEY_CMD_ARGS = "CMD_ARGS";
public class LettuceMonoCreationAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Map<String, String> extractCommand(
@ -26,7 +23,7 @@ public class MonoCreationAdvice {
@Advice.Return(readOnly = false) Mono<?> publisher) {
boolean finishSpanOnClose = LettuceInstrumentationUtil.doFinishSpanEarly(commandMap);
MonoDualConsumer mdc = new MonoDualConsumer(commandMap, finishSpanOnClose);
LettuceMonoDualConsumer mdc = new LettuceMonoDualConsumer(commandMap, finishSpanOnClose);
publisher = publisher.doOnSubscribe(mdc);
// register the call back to close the span only if necessary
if (!finishSpanOnClose) {

View File

@ -13,14 +13,14 @@ import java.util.function.Consumer;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
public class MonoDualConsumer<R, T, U extends Throwable>
public class LettuceMonoDualConsumer<R, T, U extends Throwable>
implements Consumer<R>, BiConsumer<T, Throwable> {
private Span span = null;
private final Map<String, String> commandMap;
private final boolean finishSpanOnClose;
public MonoDualConsumer(Map<String, String> commandMap, boolean finishSpanOnClose) {
public LettuceMonoDualConsumer(Map<String, String> commandMap, boolean finishSpanOnClose) {
this.commandMap = commandMap;
this.finishSpanOnClose = finishSpanOnClose;
}

View File

@ -27,7 +27,7 @@ import static datadog.trace.agent.test.ListWriterAssert.assertTraces
class LettuceAsyncClientTest extends AgentTestRunner {
static {
System.setProperty("dd.integration.redis.enabled", "true")
System.setProperty("dd.integration.lettuce.enabled", "true")
}
@Shared
@ -137,7 +137,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
"db.redis.url" DB_ADDR_NON_EXISTENT
"db.redis.dbIndex" 0
"db.type" "redis"
errorTags CompletionException
errorTags CompletionException, String
"peer.hostname" HOST
"peer.port" INCORRECT_PORT
"span.kind" "client"

View File

@ -14,7 +14,7 @@ import static datadog.trace.agent.test.ListWriterAssert.assertTraces
class LettuceReactiveClientTest extends AgentTestRunner {
static {
System.setProperty("dd.integration.redis.enabled", "true")
System.setProperty("dd.integration.lettuce.enabled", "true")
}
@Shared

View File

@ -15,7 +15,7 @@ import static datadog.trace.agent.test.ListWriterAssert.assertTraces
class LettuceSyncClientTest extends AgentTestRunner {
static {
System.setProperty("dd.integration.redis.enabled", "true")
System.setProperty("dd.integration.lettuce.enabled", "true")
}
@Shared
@ -117,7 +117,7 @@ class LettuceSyncClientTest extends AgentTestRunner {
"db.redis.url" DB_ADDR_NON_EXISTENT
"db.redis.dbIndex" 0
"db.type" "redis"
errorTags CompletionException
errorTags CompletionException, String
"peer.hostname" HOST
"peer.port" INCORRECT_PORT
"span.kind" "client"

View File

@ -40,10 +40,6 @@ class TagsAssert {
if (message != null) {
methodMissing("error.msg", [message].toArray())
} else {
// don't make the message check mandatory, in case of exception messages that change on every run,
// i.e. random port that is destined to fail every time
assertedTags.add("error.msg")
}
}