Fix code with suggestions from Tyler regarding previous commit.
no longer includes the command argument if the redis command being called is AUTH since it contains sensitive information.
This commit is contained in:
parent
ae1d9d7c52
commit
989a259ec2
|
@ -1,10 +1,37 @@
|
||||||
apply from: "${rootDir}/gradle/java.gradle"
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main_java8 {
|
||||||
|
java.srcDirs "${project.projectDir}/src/main/java8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileMain_java8Java {
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
targetCompatibility = 1.8
|
targetCompatibility = 1.8
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'org.unbroken-dome.test-sets'
|
||||||
|
|
||||||
|
testSets {
|
||||||
|
latestDepTest {
|
||||||
|
dirName = 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly group: 'io.lettuce', name: 'lettuce-core', version: '5.0.4.RELEASE'
|
main_java8CompileOnly group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE'
|
||||||
|
|
||||||
|
main_java8Compile project(':dd-java-agent:agent-tooling')
|
||||||
|
|
||||||
|
main_java8Compile deps.bytebuddy
|
||||||
|
main_java8Compile deps.opentracing
|
||||||
|
|
||||||
|
compileOnly sourceSets.main_java8.compileClasspath
|
||||||
|
|
||||||
|
compile sourceSets.main_java8.output
|
||||||
|
|
||||||
|
compileOnly group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE'
|
||||||
|
|
||||||
compile project(':dd-java-agent:agent-tooling')
|
compile project(':dd-java-agent:agent-tooling')
|
||||||
|
|
||||||
|
@ -16,5 +43,15 @@ dependencies {
|
||||||
testCompile project(':dd-java-agent:testing')
|
testCompile project(':dd-java-agent:testing')
|
||||||
|
|
||||||
testCompile group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6'
|
testCompile group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6'
|
||||||
testCompile group: 'io.lettuce', name: 'lettuce-core', version: '5.0.4.RELEASE'
|
testCompile group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.latestDepTestCompile {
|
||||||
|
resolutionStrategy {
|
||||||
|
force group: 'io.lettuce', name: 'lettuce-core', version: '+'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testJava8Only += '**/LettuceAsyncClientTest.class'
|
||||||
|
testJava8Only += '**/LettuceSyncClientTest.class'
|
||||||
|
|
||||||
|
|
|
@ -7,27 +7,17 @@ import datadog.trace.agent.tooling.DDAdvice;
|
||||||
import datadog.trace.agent.tooling.DDTransformers;
|
import datadog.trace.agent.tooling.DDTransformers;
|
||||||
import datadog.trace.agent.tooling.HelperInjector;
|
import datadog.trace.agent.tooling.HelperInjector;
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import io.lettuce.core.protocol.AsyncCommand;
|
|
||||||
import io.lettuce.core.protocol.RedisCommand;
|
|
||||||
import io.opentracing.Scope;
|
|
||||||
import io.opentracing.Span;
|
|
||||||
import io.opentracing.tag.Tags;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import java.util.Collections;
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable {
|
public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable {
|
||||||
|
|
||||||
private static final HelperInjector REDIS_ASYNC_HELPERS =
|
private static final HelperInjector REDIS_ASYNC_HELPERS =
|
||||||
new HelperInjector(RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction");
|
new HelperInjector(
|
||||||
private static final String SERVICE_NAME = "redis";
|
RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction");
|
||||||
private static final String COMPONENT_NAME = SERVICE_NAME + "-client";
|
|
||||||
|
|
||||||
public RedisAsyncCommandsInstrumentation() {
|
public RedisAsyncCommandsInstrumentation() {
|
||||||
super(SERVICE_NAME);
|
super("redis");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,56 +40,4 @@ public class RedisAsyncCommandsInstrumentation extends Instrumenter.Configurable
|
||||||
RedisAsyncCommandsAdvice.class.getName()))
|
RedisAsyncCommandsAdvice.class.getName()))
|
||||||
.asDecorator();
|
.asDecorator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RedisAsyncCommandsAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
|
||||||
public static Scope startSpan(@Advice.Argument(0) final RedisCommand command) {
|
|
||||||
final Scope scope = GlobalTracer.get().buildSpan(SERVICE_NAME + ".query").startActive(false);
|
|
||||||
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.DB_TYPE.set(span, SERVICE_NAME);
|
|
||||||
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
|
|
||||||
Tags.COMPONENT.set(span, COMPONENT_NAME);
|
|
||||||
|
|
||||||
String commandName = "Unknown Redis Command";
|
|
||||||
String commandArgs = null;
|
|
||||||
if (command != null) {
|
|
||||||
// get the redis command name (i.e. GET, SET, HMSET, etc)
|
|
||||||
if (command.getType() != null) {
|
|
||||||
commandName = command.getType().name();
|
|
||||||
}
|
|
||||||
// get the arguments passed into the redis command
|
|
||||||
if (command.getArgs() != null) {
|
|
||||||
commandArgs = command.getArgs().toCommandString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span.setTag(DDTags.RESOURCE_NAME, commandName);
|
|
||||||
span.setTag("db.redis.command.args", commandArgs);
|
|
||||||
span.setTag(DDTags.SERVICE_NAME, SERVICE_NAME);
|
|
||||||
span.setTag(DDTags.SPAN_TYPE, SERVICE_NAME);
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.Enter final Scope scope,
|
|
||||||
@Advice.Thrown final Throwable throwable,
|
|
||||||
@Advice.Return(readOnly = false) final AsyncCommand<?, ?, ?> asyncCommand) {
|
|
||||||
|
|
||||||
if (throwable != null) {
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.ERROR.set(span, true);
|
|
||||||
span.log(Collections.singletonMap("error.object", throwable));
|
|
||||||
scope.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// close spans on error or normal completion
|
|
||||||
asyncCommand.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,30 +7,17 @@ import datadog.trace.agent.tooling.DDAdvice;
|
||||||
import datadog.trace.agent.tooling.DDTransformers;
|
import datadog.trace.agent.tooling.DDTransformers;
|
||||||
import datadog.trace.agent.tooling.HelperInjector;
|
import datadog.trace.agent.tooling.HelperInjector;
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import io.lettuce.core.*;
|
|
||||||
import io.opentracing.Scope;
|
|
||||||
import io.opentracing.Span;
|
|
||||||
import io.opentracing.tag.Tags;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import java.util.Collections;
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public final class RedisClientInstrumentation extends Instrumenter.Configurable {
|
public final class RedisClientInstrumentation extends Instrumenter.Configurable {
|
||||||
|
|
||||||
private static final HelperInjector REDIS_ASYNC_HELPERS =
|
private static final HelperInjector REDIS_ASYNC_HELPERS =
|
||||||
new HelperInjector(RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction");
|
new HelperInjector(
|
||||||
|
RedisAsyncCommandsInstrumentation.class.getPackage().getName() + ".RedisAsyncBiFunction");
|
||||||
public static final String SERVICE_NAME = "redis";
|
|
||||||
public static final String COMPONENT_NAME = SERVICE_NAME + "-client";
|
|
||||||
public static final String RESOURCE_NAME_PREFIX = "CONNECT:";
|
|
||||||
public static final String REDIS_URL_TAG_NAME = "db.redis.url";
|
|
||||||
public static final String REDIS_DB_INDEX_TAG_NAME = "db.redis.dbIndex";
|
|
||||||
|
|
||||||
public RedisClientInstrumentation() {
|
public RedisClientInstrumentation() {
|
||||||
super(SERVICE_NAME);
|
super("redis");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,9 +28,7 @@ public final class RedisClientInstrumentation extends Instrumenter.Configurable
|
||||||
@Override
|
@Override
|
||||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||||
return agentBuilder
|
return agentBuilder
|
||||||
.type(
|
.type(named("io.lettuce.core.RedisClient"))
|
||||||
named("io.lettuce.core.RedisClient")
|
|
||||||
.and(hasSuperType(named("io.lettuce.core.AbstractRedisClient"))))
|
|
||||||
.transform(DDTransformers.defaultTransformers())
|
.transform(DDTransformers.defaultTransformers())
|
||||||
.transform(REDIS_ASYNC_HELPERS)
|
.transform(REDIS_ASYNC_HELPERS)
|
||||||
.transform(
|
.transform(
|
||||||
|
@ -58,45 +43,4 @@ public final class RedisClientInstrumentation extends Instrumenter.Configurable
|
||||||
ConnectionFutureAdvice.class.getName()))
|
ConnectionFutureAdvice.class.getName()))
|
||||||
.asDecorator();
|
.asDecorator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ConnectionFutureAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
|
||||||
public static Scope startSpan(@Advice.Argument(1) final RedisURI redisURI) {
|
|
||||||
final Scope scope = GlobalTracer.get().buildSpan(SERVICE_NAME + ".query").startActive(false);
|
|
||||||
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.DB_TYPE.set(span, SERVICE_NAME);
|
|
||||||
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
|
|
||||||
Tags.COMPONENT.set(span, COMPONENT_NAME);
|
|
||||||
|
|
||||||
final String url =
|
|
||||||
redisURI.getHost() + ":" + redisURI.getPort() + "/" + redisURI.getDatabase();
|
|
||||||
span.setTag(REDIS_URL_TAG_NAME, url);
|
|
||||||
span.setTag(REDIS_DB_INDEX_TAG_NAME, redisURI.getDatabase());
|
|
||||||
span.setTag(DDTags.RESOURCE_NAME, RESOURCE_NAME_PREFIX + url);
|
|
||||||
span.setTag(DDTags.SERVICE_NAME, SERVICE_NAME);
|
|
||||||
span.setTag(DDTags.SPAN_TYPE, SERVICE_NAME);
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.Enter final Scope scope,
|
|
||||||
@Advice.Thrown final Throwable throwable,
|
|
||||||
@Advice.Return(readOnly = false) final ConnectionFuture connectionFuture) {
|
|
||||||
if (throwable != null) {
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.ERROR.set(span, true);
|
|
||||||
span.log(Collections.singletonMap("error.object", throwable));
|
|
||||||
scope.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// close spans on error or normal completion
|
|
||||||
connectionFuture.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package datadog.trace.instrumentation.lettuce;
|
||||||
|
|
||||||
|
import datadog.trace.api.DDTags;
|
||||||
|
import io.lettuce.core.ConnectionFuture;
|
||||||
|
import io.lettuce.core.RedisURI;
|
||||||
|
import io.opentracing.Scope;
|
||||||
|
import io.opentracing.Span;
|
||||||
|
import io.opentracing.tag.Tags;
|
||||||
|
import io.opentracing.util.GlobalTracer;
|
||||||
|
import java.util.Collections;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
|
public class ConnectionFutureAdvice {
|
||||||
|
|
||||||
|
public static final String SERVICE_NAME = "redis";
|
||||||
|
public static final String COMPONENT_NAME = SERVICE_NAME + "-client";
|
||||||
|
public static final String REDIS_URL_TAG_NAME = "db.redis.url";
|
||||||
|
public static final String REDIS_DB_INDEX_TAG_NAME = "db.redis.dbIndex";
|
||||||
|
public static final String RESOURCE_NAME_PREFIX = "CONNECT:";
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static Scope startSpan(@Advice.Argument(1) final RedisURI redisURI) {
|
||||||
|
final Scope scope = GlobalTracer.get().buildSpan("redis.query").startActive(false);
|
||||||
|
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.DB_TYPE.set(span, SERVICE_NAME);
|
||||||
|
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
|
||||||
|
Tags.COMPONENT.set(span, COMPONENT_NAME);
|
||||||
|
|
||||||
|
final int redisPort = redisURI.getPort();
|
||||||
|
Tags.PEER_PORT.set(span, redisPort);
|
||||||
|
final String redisHost = redisURI.getHost();
|
||||||
|
Tags.PEER_HOSTNAME.set(span, redisHost);
|
||||||
|
|
||||||
|
final String url = redisHost + ":" + redisPort + "/" + redisURI.getDatabase();
|
||||||
|
span.setTag(REDIS_URL_TAG_NAME, url);
|
||||||
|
span.setTag(REDIS_DB_INDEX_TAG_NAME, redisURI.getDatabase());
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, RESOURCE_NAME_PREFIX + url);
|
||||||
|
span.setTag(DDTags.SERVICE_NAME, SERVICE_NAME);
|
||||||
|
span.setTag(DDTags.SPAN_TYPE, SERVICE_NAME);
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void stopSpan(
|
||||||
|
@Advice.Enter final Scope scope,
|
||||||
|
@Advice.Thrown final Throwable throwable,
|
||||||
|
@Advice.Return final ConnectionFuture connectionFuture) {
|
||||||
|
if (throwable != null) {
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.ERROR.set(span, true);
|
||||||
|
span.log(Collections.singletonMap("error.object", throwable));
|
||||||
|
scope.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// close spans on error or normal completion
|
||||||
|
connectionFuture.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
|
||||||
|
scope.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,12 +6,13 @@ import java.util.Collections;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback class to close the span on an error or a success in the RedisFuture returned by
|
* Callback class to close the span on an error or a success in the RedisFuture returned by the
|
||||||
* the lettuce async API
|
* lettuce async API
|
||||||
|
*
|
||||||
* @param <T> the normal completion result
|
* @param <T> the normal completion result
|
||||||
* @param <U> the error
|
* @param <U> the error
|
||||||
* @param <R> the return type, should be null since nothing else should happen from tracing standpoint
|
* @param <R> the return type, should be null since nothing else should happen from tracing
|
||||||
* after the span is closed
|
* standpoint after the span is closed
|
||||||
*/
|
*/
|
||||||
public class RedisAsyncBiFunction<T extends Object, U extends Throwable, R extends Object>
|
public class RedisAsyncBiFunction<T extends Object, U extends Throwable, R extends Object>
|
||||||
implements BiFunction<T, Throwable, R> {
|
implements BiFunction<T, Throwable, R> {
|
|
@ -0,0 +1,70 @@
|
||||||
|
package datadog.trace.instrumentation.lettuce;
|
||||||
|
|
||||||
|
import datadog.trace.api.DDTags;
|
||||||
|
import io.lettuce.core.protocol.AsyncCommand;
|
||||||
|
import io.lettuce.core.protocol.RedisCommand;
|
||||||
|
import io.opentracing.Scope;
|
||||||
|
import io.opentracing.Span;
|
||||||
|
import io.opentracing.tag.Tags;
|
||||||
|
import io.opentracing.util.GlobalTracer;
|
||||||
|
import java.util.Collections;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
|
public class RedisAsyncCommandsAdvice {
|
||||||
|
|
||||||
|
private static final String SERVICE_NAME = "redis";
|
||||||
|
private static final String COMPONENT_NAME = SERVICE_NAME + "-client";
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static Scope startSpan(@Advice.Argument(0) final RedisCommand command) {
|
||||||
|
final Scope scope = GlobalTracer.get().buildSpan(SERVICE_NAME + ".query").startActive(false);
|
||||||
|
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.DB_TYPE.set(span, SERVICE_NAME);
|
||||||
|
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
|
||||||
|
Tags.COMPONENT.set(span, COMPONENT_NAME);
|
||||||
|
|
||||||
|
String commandName = "Redis Command";
|
||||||
|
String commandArgs = null;
|
||||||
|
if (command != null) {
|
||||||
|
// get the arguments passed into the redis command
|
||||||
|
if (command.getArgs() != null) {
|
||||||
|
commandArgs = command.getArgs().toCommandString();
|
||||||
|
}
|
||||||
|
// get the redis command name (i.e. GET, SET, HMSET, etc)
|
||||||
|
if (command.getType() != null) {
|
||||||
|
commandName = command.getType().name();
|
||||||
|
// if it is an AUTH command, then remove the extracted command arguments since it is the password
|
||||||
|
if ("AUTH".equals(commandName)) {
|
||||||
|
commandArgs = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.setTag(DDTags.RESOURCE_NAME, commandName);
|
||||||
|
span.setTag("db.command.args", commandArgs);
|
||||||
|
span.setTag(DDTags.SERVICE_NAME, SERVICE_NAME);
|
||||||
|
span.setTag(DDTags.SPAN_TYPE, SERVICE_NAME);
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void stopSpan(
|
||||||
|
@Advice.Enter final Scope scope,
|
||||||
|
@Advice.Thrown final Throwable throwable,
|
||||||
|
@Advice.Return final AsyncCommand<?, ?, ?> asyncCommand) {
|
||||||
|
|
||||||
|
if (throwable != null) {
|
||||||
|
final Span span = scope.span();
|
||||||
|
Tags.ERROR.set(span, true);
|
||||||
|
span.log(Collections.singletonMap("error.object", throwable));
|
||||||
|
scope.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// close spans on error or normal completion
|
||||||
|
asyncCommand.handleAsync(new RedisAsyncBiFunction<>(scope.span()));
|
||||||
|
scope.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import datadog.trace.agent.test.AgentTestRunner
|
import datadog.trace.agent.test.AgentTestRunner
|
||||||
import datadog.trace.instrumentation.lettuce.RedisAsyncCommandsInstrumentation
|
import datadog.trace.agent.test.TestUtils
|
||||||
import datadog.trace.instrumentation.lettuce.RedisClientInstrumentation
|
|
||||||
import io.lettuce.core.ConnectionFuture
|
import io.lettuce.core.ConnectionFuture
|
||||||
import io.lettuce.core.RedisClient
|
import io.lettuce.core.RedisClient
|
||||||
|
import io.lettuce.core.RedisConnectionException
|
||||||
import io.lettuce.core.RedisFuture
|
import io.lettuce.core.RedisFuture
|
||||||
import io.lettuce.core.RedisURI
|
import io.lettuce.core.RedisURI
|
||||||
import io.lettuce.core.api.StatefulConnection
|
import io.lettuce.core.api.StatefulConnection
|
||||||
|
@ -18,6 +18,9 @@ import java.util.function.BiFunction
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
|
|
||||||
|
import static datadog.trace.instrumentation.lettuce.ConnectionFutureAdvice.RESOURCE_NAME_PREFIX
|
||||||
|
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
|
||||||
|
|
||||||
class LettuceAsyncClientTest extends AgentTestRunner {
|
class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -26,8 +29,8 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
@Shared
|
@Shared
|
||||||
public static final String HOST = "127.0.0.1"
|
public static final String HOST = "127.0.0.1"
|
||||||
public static final int PORT = 6399
|
public static final int PORT = TestUtils.randomOpenPort()
|
||||||
public static final int INCORRECT_PORT = 9999
|
public static final int INCORRECT_PORT = TestUtils.randomOpenPort()
|
||||||
public static final int DB_INDEX = 0
|
public static final int DB_INDEX = 0
|
||||||
@Shared
|
@Shared
|
||||||
public static final String DB_ADDR = HOST + ":" + PORT + "/" + DB_INDEX
|
public static final String DB_ADDR = HOST + ":" + PORT + "/" + DB_INDEX
|
||||||
|
@ -69,10 +72,6 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
redisServer.stop()
|
redisServer.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup() {
|
|
||||||
TEST_WRITER.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
def "connect using get on ConnectionFuture"() {
|
def "connect using get on ConnectionFuture"() {
|
||||||
setup:
|
setup:
|
||||||
RedisClient testConnectionClient = RedisClient.create(EMBEDDED_DB_URI)
|
RedisClient testConnectionClient = RedisClient.create(EMBEDDED_DB_URI)
|
||||||
|
@ -83,26 +82,29 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
connection != null
|
connection != null
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName RESOURCE_NAME_PREFIX + DB_ADDR
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisClientInstrumentation.SERVICE_NAME
|
"db.redis.url" DB_ADDR
|
||||||
span.getOperationName() == "redis.query"
|
"db.redis.dbIndex" 0
|
||||||
span.getType() == RedisClientInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == RedisClientInstrumentation.RESOURCE_NAME_PREFIX + DB_ADDR
|
"peer.hostname" HOST
|
||||||
!span.context().getErrorFlag()
|
"peer.port" PORT
|
||||||
|
"span.kind" "client"
|
||||||
def tags = span.context().tags
|
"span.type" "redis"
|
||||||
tags[RedisClientInstrumentation.REDIS_URL_TAG_NAME] == DB_ADDR
|
}
|
||||||
tags[RedisClientInstrumentation.REDIS_DB_INDEX_TAG_NAME] == 0
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisClientInstrumentation.SERVICE_NAME
|
|
||||||
tags["component"] == RedisClientInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "connect exception inside the connection future"() {
|
def "connect exception inside the connection future"() {
|
||||||
|
@ -121,26 +123,30 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
expect:
|
expect:
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
connection == null
|
connection == null
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName RESOURCE_NAME_PREFIX + DB_ADDR_NON_EXISTENT
|
||||||
|
errored true
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisClientInstrumentation.SERVICE_NAME
|
"db.redis.url" DB_ADDR_NON_EXISTENT
|
||||||
span.getOperationName() == "redis.query"
|
"db.redis.dbIndex" 0
|
||||||
span.getType() == RedisClientInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == RedisClientInstrumentation.RESOURCE_NAME_PREFIX + DB_ADDR_NON_EXISTENT
|
errorTags(RedisConnectionException, "some error due to incorrect port number")
|
||||||
span.context().getErrorFlag()
|
"peer.hostname" HOST
|
||||||
|
"peer.port" INCORRECT_PORT
|
||||||
def tags = span.context().tags
|
"span.kind" "client"
|
||||||
tags[RedisClientInstrumentation.REDIS_URL_TAG_NAME] == DB_ADDR_NON_EXISTENT
|
"span.type" "redis"
|
||||||
tags[RedisClientInstrumentation.REDIS_DB_INDEX_TAG_NAME] == 0
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["component"] == RedisClientInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set command using Future get with timeout"() {
|
def "set command using Future get with timeout"() {
|
||||||
|
@ -151,24 +157,26 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == "OK"
|
res == "OK"
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
def trace = TEST_WRITER.firstTrace()
|
trace(0, 1) {
|
||||||
trace.size() == 1
|
span(0) {
|
||||||
def span = trace[0]
|
serviceName "redis"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
operationName "redis.query"
|
||||||
span.getOperationName() == "redis.query"
|
spanType "redis"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
resourceName "SET"
|
||||||
span.getResourceName() == "SET"
|
errored false
|
||||||
!span.context().getErrorFlag()
|
|
||||||
|
|
||||||
def tags = span.context().tags
|
tags {
|
||||||
tags["span.kind"] == "client"
|
defaultTags()
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"component" "redis-client"
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
tags["db.redis.command.args"] == "key<TESTKEY> value<TESTVAL>"
|
"db.command.args" "key<TESTKEY> value<TESTVAL>"
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
"span.kind" "client"
|
||||||
tags["thread.name"] != null
|
"span.type" "redis"
|
||||||
tags["thread.id"] != null
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "get command chained with thenAccept"() {
|
def "get command chained with thenAccept"() {
|
||||||
|
@ -188,27 +196,28 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
redisFuture.thenAccept(consumer)
|
redisFuture.thenAccept(consumer)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
conds.await()
|
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
TEST_WRITER.size() == 1
|
conds.await()
|
||||||
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "GET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getOperationName() == "redis.query"
|
"db.command.args" "key<TESTKEY>"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getResourceName() == "GET"
|
"span.type" "redis"
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == "key<TESTKEY>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to make sure instrumentation's chained completion stages won't interfere with user's, while still
|
// to make sure instrumentation's chained completion stages won't interfere with user's, while still
|
||||||
|
@ -216,7 +225,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
def "get non existent key command with handleAsync and chained with thenApply"() {
|
def "get non existent key command with handleAsync and chained with thenApply"() {
|
||||||
setup:
|
setup:
|
||||||
def conds = new AsyncConditions()
|
def conds = new AsyncConditions()
|
||||||
final String SUCCESS = "KEY MISSING"
|
final String successStr = "KEY MISSING"
|
||||||
BiFunction<String, Throwable, String> firstStage = new BiFunction<String, Throwable, String>() {
|
BiFunction<String, Throwable, String> firstStage = new BiFunction<String, Throwable, String>() {
|
||||||
@Override
|
@Override
|
||||||
String apply(String res, Throwable throwable) {
|
String apply(String res, Throwable throwable) {
|
||||||
|
@ -224,14 +233,14 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
assert res == null
|
assert res == null
|
||||||
assert throwable == null
|
assert throwable == null
|
||||||
}
|
}
|
||||||
return (res == null ? SUCCESS : res)
|
return (res == null ? successStr : res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Function<String, Object> secondStage = new Function<String, Object>() {
|
Function<String, Object> secondStage = new Function<String, Object>() {
|
||||||
@Override
|
@Override
|
||||||
Object apply(String input) {
|
Object apply(String input) {
|
||||||
conds.evaluate{
|
conds.evaluate{
|
||||||
assert input == SUCCESS
|
assert input == successStr
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -242,27 +251,29 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
redisFuture.handleAsync(firstStage).thenApply(secondStage)
|
redisFuture.handleAsync(firstStage).thenApply(secondStage)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
conds.await()
|
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
TEST_WRITER.size() == 1
|
conds.await()
|
||||||
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "GET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getOperationName() == "redis.query"
|
"db.command.args" "key<NON_EXISTENT_KEY>"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getResourceName() == "GET"
|
"span.type" "redis"
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def tags = span.context().tags
|
|
||||||
tags["span.kind"] == "client"
|
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == "key<NON_EXISTENT_KEY>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "command with no arguments using a biconsumer"() {
|
def "command with no arguments using a biconsumer"() {
|
||||||
|
@ -282,28 +293,27 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
redisFuture.whenCompleteAsync(biConsumer)
|
redisFuture.whenCompleteAsync(biConsumer)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
conds.await()
|
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
TEST_WRITER.size() == 1
|
conds.await()
|
||||||
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "RANDOMKEY"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
|
"component" "redis-client"
|
||||||
def span = trace[0]
|
"db.type" "redis"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getOperationName() == "redis.query"
|
"span.type" "redis"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
span.getResourceName() == "RANDOMKEY"
|
}
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
|
||||||
tags["span.kind"] == "client"
|
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == null
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "hash set and then nest apply to hash getall"() {
|
def "hash set and then nest apply to hash getall"() {
|
||||||
|
@ -315,8 +325,6 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
hmsetFuture.thenApplyAsync(new Function<String, Object>() {
|
hmsetFuture.thenApplyAsync(new Function<String, Object>() {
|
||||||
@Override
|
@Override
|
||||||
Object apply(String setResult) {
|
Object apply(String setResult) {
|
||||||
TEST_WRITER.waitForTraces(1)
|
|
||||||
TEST_WRITER.start()
|
|
||||||
conds.evaluate {
|
conds.evaluate {
|
||||||
assert setResult == "OK"
|
assert setResult == "OK"
|
||||||
}
|
}
|
||||||
|
@ -343,25 +351,45 @@ class LettuceAsyncClientTest extends AgentTestRunner {
|
||||||
})
|
})
|
||||||
|
|
||||||
then:
|
then:
|
||||||
|
TEST_WRITER.waitForTraces(2)
|
||||||
conds.await()
|
conds.await()
|
||||||
TEST_WRITER.waitForTraces(1)
|
assertTraces(TEST_WRITER, 2) {
|
||||||
def trace = TEST_WRITER.firstTrace()
|
trace(0, 1) {
|
||||||
trace.size() == 1
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "HMSET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def span = trace[0]
|
tags {
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
defaultTags()
|
||||||
span.getOperationName() == "redis.query"
|
"component" "redis-client"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == "HGETALL"
|
"db.command.args" "key<user> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
|
||||||
!span.context().getErrorFlag()
|
"span.kind" "client"
|
||||||
|
"span.type" "redis"
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
trace(1, 1) {
|
||||||
tags["db.redis.command.args"] == "key<user>"
|
span(0) {
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
serviceName "redis"
|
||||||
tags["thread.name"] != null
|
operationName "redis.query"
|
||||||
tags["thread.id"] != null
|
spanType "redis"
|
||||||
|
resourceName "HGETALL"
|
||||||
|
errored false
|
||||||
|
|
||||||
|
tags {
|
||||||
|
defaultTags()
|
||||||
|
"component" "redis-client"
|
||||||
|
"db.type" "redis"
|
||||||
|
"db.command.args" "key<user>"
|
||||||
|
"span.kind" "client"
|
||||||
|
"span.type" "redis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import datadog.trace.agent.test.AgentTestRunner
|
import datadog.trace.agent.test.AgentTestRunner
|
||||||
import datadog.trace.instrumentation.lettuce.RedisAsyncCommandsInstrumentation
|
import datadog.trace.agent.test.TestUtils
|
||||||
import datadog.trace.instrumentation.lettuce.RedisClientInstrumentation
|
|
||||||
import io.lettuce.core.RedisClient
|
import io.lettuce.core.RedisClient
|
||||||
import io.lettuce.core.RedisConnectionException
|
import io.lettuce.core.RedisConnectionException
|
||||||
import io.lettuce.core.api.StatefulConnection
|
import io.lettuce.core.api.StatefulConnection
|
||||||
|
@ -8,6 +7,9 @@ import io.lettuce.core.api.sync.RedisCommands
|
||||||
import redis.embedded.RedisServer
|
import redis.embedded.RedisServer
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
|
import static datadog.trace.instrumentation.lettuce.ConnectionFutureAdvice.RESOURCE_NAME_PREFIX
|
||||||
|
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
|
||||||
|
|
||||||
class LettuceSyncClientTest extends AgentTestRunner {
|
class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -16,12 +18,13 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
@Shared
|
@Shared
|
||||||
public static final String HOST = "127.0.0.1"
|
public static final String HOST = "127.0.0.1"
|
||||||
public static final int PORT = 6399
|
public static final int PORT = TestUtils.randomOpenPort()
|
||||||
|
public static final int INCORRECT_PORT = TestUtils.randomOpenPort()
|
||||||
public static final int DB_INDEX = 0
|
public static final int DB_INDEX = 0
|
||||||
@Shared
|
@Shared
|
||||||
public static final String DB_ADDR = HOST + ":" + PORT + "/" + DB_INDEX
|
public static final String DB_ADDR = HOST + ":" + PORT + "/" + DB_INDEX
|
||||||
@Shared
|
@Shared
|
||||||
public static final String DB_ADDR_NON_EXISTENT = HOST + ":" + 9999 + "/" + DB_INDEX
|
public static final String DB_ADDR_NON_EXISTENT = HOST + ":" + INCORRECT_PORT + "/" + DB_INDEX
|
||||||
@Shared
|
@Shared
|
||||||
public static final String DB_URI_NON_EXISTENT = "redis://" + DB_ADDR_NON_EXISTENT
|
public static final String DB_URI_NON_EXISTENT = "redis://" + DB_ADDR_NON_EXISTENT
|
||||||
public static final String EMBEDDED_DB_URI = "redis://" + DB_ADDR
|
public static final String EMBEDDED_DB_URI = "redis://" + DB_ADDR
|
||||||
|
@ -48,7 +51,6 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
]
|
]
|
||||||
|
|
||||||
def setupSpec() {
|
def setupSpec() {
|
||||||
println "Using redis: $redisServer.args"
|
|
||||||
redisServer.start()
|
redisServer.start()
|
||||||
StatefulConnection connection = redisClient.connect()
|
StatefulConnection connection = redisClient.connect()
|
||||||
syncCommands = connection.sync()
|
syncCommands = connection.sync()
|
||||||
|
@ -58,10 +60,6 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
redisServer.stop()
|
redisServer.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup() {
|
|
||||||
TEST_WRITER.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
def "connect"() {
|
def "connect"() {
|
||||||
setup:
|
setup:
|
||||||
RedisClient testConnectionClient = RedisClient.create(EMBEDDED_DB_URI)
|
RedisClient testConnectionClient = RedisClient.create(EMBEDDED_DB_URI)
|
||||||
|
@ -69,26 +67,29 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName RESOURCE_NAME_PREFIX + DB_ADDR
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisClientInstrumentation.SERVICE_NAME
|
"db.redis.url" DB_ADDR
|
||||||
span.getOperationName() == "redis.query"
|
"db.redis.dbIndex" 0
|
||||||
span.getType() == RedisClientInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == RedisClientInstrumentation.RESOURCE_NAME_PREFIX + DB_ADDR
|
"peer.hostname" HOST
|
||||||
!span.context().getErrorFlag()
|
"peer.port" PORT
|
||||||
|
"span.kind" "client"
|
||||||
def tags = span.context().tags
|
"span.type" "redis"
|
||||||
tags[RedisClientInstrumentation.REDIS_URL_TAG_NAME] == DB_ADDR
|
}
|
||||||
tags[RedisClientInstrumentation.REDIS_DB_INDEX_TAG_NAME] == 0
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisClientInstrumentation.SERVICE_NAME
|
|
||||||
tags["component"] == RedisClientInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "connect exception"() {
|
def "connect exception"() {
|
||||||
|
@ -100,26 +101,30 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
TEST_WRITER.waitForTraces(1)
|
TEST_WRITER.waitForTraces(1)
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName RESOURCE_NAME_PREFIX + DB_ADDR_NON_EXISTENT
|
||||||
|
errored true
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisClientInstrumentation.SERVICE_NAME
|
"db.redis.url" DB_ADDR_NON_EXISTENT
|
||||||
span.getOperationName() == "redis.query"
|
"db.redis.dbIndex" 0
|
||||||
span.getType() == RedisClientInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == RedisClientInstrumentation.RESOURCE_NAME_PREFIX + DB_ADDR_NON_EXISTENT
|
errorTags(RedisConnectionException, "some error due to incorrect port number")
|
||||||
span.context().getErrorFlag()
|
"peer.hostname" HOST
|
||||||
|
"peer.port" INCORRECT_PORT
|
||||||
def tags = span.context().tags
|
"span.kind" "client"
|
||||||
tags[RedisClientInstrumentation.REDIS_URL_TAG_NAME] == DB_ADDR_NON_EXISTENT
|
"span.type" "redis"
|
||||||
tags[RedisClientInstrumentation.REDIS_DB_INDEX_TAG_NAME] == 0
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisClientInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["component"] == RedisClientInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "set command"() {
|
def "set command"() {
|
||||||
|
@ -129,26 +134,26 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == "OK"
|
res == "OK"
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "SET"
|
||||||
|
errored false
|
||||||
|
|
||||||
|
tags {
|
||||||
def trace = TEST_WRITER.firstTrace()
|
defaultTags()
|
||||||
trace.size() == 1
|
"component" "redis-client"
|
||||||
def span = trace[0]
|
"db.type" "redis"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.command.args" "key<TESTKEY> value<TESTVAL>"
|
||||||
span.getOperationName() == "redis.query"
|
"span.kind" "client"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.type" "redis"
|
||||||
span.getResourceName() == "SET"
|
}
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == "key<TESTKEY> value<TESTVAL>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "get command"() {
|
def "get command"() {
|
||||||
|
@ -158,25 +163,26 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == "TESTVAL"
|
res == "TESTVAL"
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "GET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getOperationName() == "redis.query"
|
"db.command.args" "key<TESTKEY>"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getResourceName() == "GET"
|
"span.type" "redis"
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == "key<TESTKEY>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "get non existent key command"() {
|
def "get non existent key command"() {
|
||||||
|
@ -186,25 +192,26 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == null
|
res == null
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "GET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
def span = trace[0]
|
"component" "redis-client"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getOperationName() == "redis.query"
|
"db.command.args" "key<NON_EXISTENT_KEY>"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getResourceName() == "GET"
|
"span.type" "redis"
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == "key<NON_EXISTENT_KEY>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "command with no arguments"() {
|
def "command with no arguments"() {
|
||||||
|
@ -214,26 +221,25 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
keyRetrieved == "TESTKEY"
|
keyRetrieved == "TESTKEY"
|
||||||
TEST_WRITER.size() == 1
|
assertTraces(TEST_WRITER, 1) {
|
||||||
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "RANDOMKEY"
|
||||||
|
errored false
|
||||||
|
|
||||||
def trace = TEST_WRITER.firstTrace()
|
tags {
|
||||||
trace.size() == 1
|
defaultTags()
|
||||||
|
"component" "redis-client"
|
||||||
def span = trace[0]
|
"db.type" "redis"
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"span.kind" "client"
|
||||||
span.getOperationName() == "redis.query"
|
"span.type" "redis"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
span.getResourceName() == "RANDOMKEY"
|
}
|
||||||
!span.context().getErrorFlag()
|
}
|
||||||
|
}
|
||||||
def tags = span.context().tags
|
|
||||||
tags["span.kind"] == "client"
|
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
|
||||||
tags["db.redis.command.args"] == null
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "list command"() {
|
def "list command"() {
|
||||||
|
@ -243,24 +249,26 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == 1
|
res == 1
|
||||||
def trace = TEST_WRITER.firstTrace()
|
assertTraces(TEST_WRITER, 1) {
|
||||||
trace.size() == 1
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "LPUSH"
|
||||||
|
errored false
|
||||||
|
|
||||||
def span = trace[0]
|
tags {
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
defaultTags()
|
||||||
span.getOperationName() == "redis.query"
|
"component" "redis-client"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == "LPUSH"
|
"db.command.args" "key<TESTLIST> value<TESTLIST ELEMENT>"
|
||||||
!span.context().getErrorFlag()
|
"span.kind" "client"
|
||||||
|
"span.type" "redis"
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.redis.command.args"] == "key<TESTLIST> value<TESTLIST ELEMENT>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "hash set command"() {
|
def "hash set command"() {
|
||||||
|
@ -270,24 +278,26 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == "OK"
|
res == "OK"
|
||||||
def trace = TEST_WRITER.firstTrace()
|
assertTraces(TEST_WRITER, 1) {
|
||||||
trace.size() == 1
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "HMSET"
|
||||||
|
errored false
|
||||||
|
|
||||||
def span = trace[0]
|
tags {
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
defaultTags()
|
||||||
span.getOperationName() == "redis.query"
|
"component" "redis-client"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == "HMSET"
|
"db.command.args" "key<user> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
|
||||||
!span.context().getErrorFlag()
|
"span.kind" "client"
|
||||||
|
"span.type" "redis"
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.redis.command.args"] == "key<user> key<firstname> value<John> key<lastname> value<Doe> key<age> value<53>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "hash getall command"() {
|
def "hash getall command"() {
|
||||||
|
@ -297,23 +307,25 @@ class LettuceSyncClientTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
res == testHashMap
|
res == testHashMap
|
||||||
def trace = TEST_WRITER.firstTrace()
|
assertTraces(TEST_WRITER, 1) {
|
||||||
trace.size() == 1
|
trace(0, 1) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "redis"
|
||||||
|
operationName "redis.query"
|
||||||
|
spanType "redis"
|
||||||
|
resourceName "HGETALL"
|
||||||
|
errored false
|
||||||
|
|
||||||
def span = trace[0]
|
tags {
|
||||||
span.getServiceName() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
defaultTags()
|
||||||
span.getOperationName() == "redis.query"
|
"component" "redis-client"
|
||||||
span.getType() == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
"db.type" "redis"
|
||||||
span.getResourceName() == "HGETALL"
|
"db.command.args" "key<user>"
|
||||||
!span.context().getErrorFlag()
|
"span.kind" "client"
|
||||||
|
"span.type" "redis"
|
||||||
def tags = span.context().tags
|
}
|
||||||
tags["span.kind"] == "client"
|
}
|
||||||
tags["span.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.type"] == RedisAsyncCommandsInstrumentation.SERVICE_NAME
|
}
|
||||||
tags["db.redis.command.args"] == "key<user>"
|
|
||||||
tags["component"] == RedisAsyncCommandsInstrumentation.COMPONENT_NAME
|
|
||||||
tags["thread.name"] != null
|
|
||||||
tags["thread.id"] != null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue