diff --git a/instrumentation/jedis/jedis-1.4/javaagent/jedis-1.4-javaagent.gradle b/instrumentation/jedis/jedis-1.4/javaagent/jedis-1.4-javaagent.gradle index 00d362413e..a462c24caa 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/jedis-1.4-javaagent.gradle +++ b/instrumentation/jedis/jedis-1.4/javaagent/jedis-1.4-javaagent.gradle @@ -12,6 +12,9 @@ muzzle { dependencies { library "redis.clients:jedis:1.4.0" + compileOnly deps.autoValueAnnotations + annotationProcessor deps.autoValue + // Jedis 3.0 has API changes that prevent instrumentation from applying latestDepTestLibrary "redis.clients:jedis:2.+" } diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java deleted file mode 100644 index a2e38d44b1..0000000000 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; - -import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.instrumentation.api.tracer.net.NetPeerAttributes; -import io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.CommandWithArgs; -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValues; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.List; -import redis.clients.jedis.Connection; -import redis.clients.jedis.Protocol.Command; - -public class JedisClientTracer extends DatabaseClientTracer { - private static final JedisClientTracer TRACER = new JedisClientTracer(); - - private JedisClientTracer() { - super(NetPeerAttributes.INSTANCE); - } - - public static JedisClientTracer tracer() { - return TRACER; - } - - @Override - protected String sanitizeStatement(CommandWithArgs command) { - return RedisCommandSanitizer.sanitize(command.getStringCommand(), command.getArgs()); - } - - @Override - protected String spanName( - Connection connection, CommandWithArgs command, String sanitizedStatement) { - return command.getStringCommand(); - } - - @Override - protected String dbSystem(Connection connection) { - return DbSystemValues.REDIS; - } - - @Override - protected String dbConnectionString(Connection connection) { - return connection.getHost() + ":" + connection.getPort(); - } - - @Override - protected InetSocketAddress peerAddress(Connection connection) { - return new InetSocketAddress(connection.getHost(), connection.getPort()); - } - - @Override - protected String dbStatement( - Connection connection, CommandWithArgs command, String sanitizedStatement) { - return sanitizedStatement; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jedis-1.4"; - } - - public static final class CommandWithArgs { - private static final byte[][] NO_ARGS = new byte[0][]; - - private final Command command; - private final byte[][] args; - - public CommandWithArgs(Command command, byte[][] args) { - this.command = command; - this.args = args; - } - - public CommandWithArgs(Command command) { - this(command, NO_ARGS); - } - - private String getStringCommand() { - return command.name(); - } - - private List getArgs() { - return Arrays.asList(args); - } - } -} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesExtractor.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesExtractor.java new file mode 100644 index 0000000000..8418dfd4fa --- /dev/null +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesExtractor.java @@ -0,0 +1,44 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; + +import io.opentelemetry.instrumentation.api.db.RedisCommandSanitizer; +import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; + +final class JedisDbAttributesExtractor extends DbAttributesExtractor { + @Override + protected String system(JedisRequest request) { + return SemanticAttributes.DbSystemValues.REDIS; + } + + @Override + @Nullable + protected String user(JedisRequest request) { + return null; + } + + @Override + protected String name(JedisRequest request) { + return null; + } + + @Override + protected String connectionString(JedisRequest request) { + return request.getConnectionString(); + } + + @Override + protected String statement(JedisRequest request) { + return RedisCommandSanitizer.sanitize(request.getCommand().name(), request.getArgs()); + } + + @Override + protected String operation(JedisRequest request) { + return request.getCommand().name(); + } +} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java index f9230e1f8e..3766ca0703 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java @@ -7,7 +7,8 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; -import static io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.tracer; +import static io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisInstrumenters.instrumenter; +import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static net.bytebuddy.matcher.ElementMatchers.is; import static net.bytebuddy.matcher.ElementMatchers.isMethod; @@ -22,7 +23,6 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; -import io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.CommandWithArgs; import java.util.List; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -80,32 +80,31 @@ public class JedisInstrumentationModule extends InstrumentationModule { public static void onEnter( @Advice.This Connection connection, @Advice.Argument(0) Command command, + @Advice.Local("otelJedisRequest") JedisRequest request, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { Context parentContext = currentContext(); - if (!tracer().shouldStartSpan(parentContext)) { + request = JedisRequest.create(connection, command); + if (!instrumenter().shouldStart(parentContext, request)) { return; } - context = tracer().startSpan(parentContext, connection, new CommandWithArgs(command)); + context = instrumenter().start(parentContext, request); scope = context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Thrown Throwable throwable, + @Advice.Local("otelJedisRequest") JedisRequest request, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { if (scope == null) { return; } - scope.close(); - if (throwable != null) { - tracer().endExceptionally(context, throwable); - } else { - tracer().end(context); - } + scope.close(); + instrumenter().end(context, request, null, throwable); } } @@ -116,20 +115,23 @@ public class JedisInstrumentationModule extends InstrumentationModule { @Advice.This Connection connection, @Advice.Argument(0) Command command, @Advice.Argument(1) byte[][] args, + @Advice.Local("otelJedisRequest") JedisRequest request, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { Context parentContext = currentContext(); - if (!tracer().shouldStartSpan(parentContext)) { + request = JedisRequest.create(connection, command, asList(args)); + if (!instrumenter().shouldStart(parentContext, request)) { return; } - context = tracer().startSpan(parentContext, connection, new CommandWithArgs(command, args)); + context = instrumenter().start(parentContext, request); scope = context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Thrown Throwable throwable, + @Advice.Local("otelJedisRequest") JedisRequest request, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { if (scope == null) { @@ -137,11 +139,7 @@ public class JedisInstrumentationModule extends InstrumentationModule { } scope.close(); - if (throwable != null) { - tracer().endExceptionally(context, throwable); - } else { - tracer().end(context); - } + instrumenter().end(context, request, null, throwable); } } } diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumenters.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumenters.java new file mode 100644 index 0000000000..3568a7bfaa --- /dev/null +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumenters.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.db.DbSpanNameExtractor; + +public final class JedisInstrumenters { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.javaagent.jedis-1.4"; + + private static final Instrumenter INSTRUMENTER; + + static { + DbAttributesExtractor attributesExtractor = new JedisDbAttributesExtractor(); + SpanNameExtractor spanName = DbSpanNameExtractor.create(attributesExtractor); + + INSTRUMENTER = + Instrumenter.newBuilder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanName) + .addAttributesExtractor(attributesExtractor) + .addAttributesExtractor(new JedisNetAttributesExtractor()) + .newInstrumenter(SpanKindExtractor.alwaysClient()); + } + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private JedisInstrumenters() {} +} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisNetAttributesExtractor.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisNetAttributesExtractor.java new file mode 100644 index 0000000000..611451cb80 --- /dev/null +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisNetAttributesExtractor.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; + +import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; +import org.checkerframework.checker.nullness.qual.Nullable; + +final class JedisNetAttributesExtractor extends NetAttributesExtractor { + + @Override + @Nullable + protected String transport(JedisRequest request) { + return null; + } + + @Override + protected String peerName(JedisRequest request, @Nullable Void response) { + return request.getConnection().getHost(); + } + + @Override + protected Integer peerPort(JedisRequest request, @Nullable Void response) { + return request.getConnection().getPort(); + } + + @Override + @Nullable + protected String peerIp(JedisRequest request, @Nullable Void response) { + return null; + } +} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisRequest.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisRequest.java new file mode 100644 index 0000000000..94ceab0ba1 --- /dev/null +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisRequest.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; + +import static java.util.Collections.emptyList; + +import com.google.auto.value.AutoValue; +import java.util.List; +import redis.clients.jedis.Connection; +import redis.clients.jedis.Protocol; + +@AutoValue +public abstract class JedisRequest { + + public abstract Connection getConnection(); + + public abstract Protocol.Command getCommand(); + + public abstract List getArgs(); + + public String getConnectionString() { + return getConnection().getHost() + ":" + getConnection().getPort(); + } + + public static JedisRequest create(Connection connection, Protocol.Command command) { + return new AutoValue_JedisRequest(connection, command, emptyList()); + } + + public static JedisRequest create( + Connection connection, Protocol.Command command, List args) { + return new AutoValue_JedisRequest(connection, command, args); + } +} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy b/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy index 5d299e726f..055c3ac856 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy @@ -51,7 +51,7 @@ class JedisClientTest extends AgentInstrumentationSpecification { "$SemanticAttributes.DB_SYSTEM.key" "redis" "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" + "$SemanticAttributes.DB_OPERATION.key" "SET" "$SemanticAttributes.NET_PEER_NAME.key" "localhost" "$SemanticAttributes.NET_PEER_PORT.key" port } @@ -77,7 +77,7 @@ class JedisClientTest extends AgentInstrumentationSpecification { "$SemanticAttributes.DB_SYSTEM.key" "redis" "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" + "$SemanticAttributes.DB_OPERATION.key" "SET" "$SemanticAttributes.NET_PEER_NAME.key" "localhost" "$SemanticAttributes.NET_PEER_PORT.key" port } @@ -91,7 +91,7 @@ class JedisClientTest extends AgentInstrumentationSpecification { "$SemanticAttributes.DB_SYSTEM.key" "redis" "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" "$SemanticAttributes.DB_STATEMENT.key" "GET foo" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" + "$SemanticAttributes.DB_OPERATION.key" "GET" "$SemanticAttributes.NET_PEER_NAME.key" "localhost" "$SemanticAttributes.NET_PEER_PORT.key" port } @@ -117,7 +117,7 @@ class JedisClientTest extends AgentInstrumentationSpecification { "$SemanticAttributes.DB_SYSTEM.key" "redis" "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" + "$SemanticAttributes.DB_OPERATION.key" "SET" "$SemanticAttributes.NET_PEER_NAME.key" "localhost" "$SemanticAttributes.NET_PEER_PORT.key" port } @@ -131,7 +131,7 @@ class JedisClientTest extends AgentInstrumentationSpecification { "$SemanticAttributes.DB_SYSTEM.key" "redis" "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" + "$SemanticAttributes.DB_OPERATION.key" "RANDOMKEY" "$SemanticAttributes.NET_PEER_NAME.key" "localhost" "$SemanticAttributes.NET_PEER_PORT.key" port }