Convert Rediscala to Instrumenter API
MODIFY
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/OnCompleteHandler.java
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/OnCompleteHandler.java
package io.opentelemetry.javaagent.instrumentation.rediscala;
-import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaClientTracer.tracer;
+import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaSingletons.instrumenter;
import io.opentelemetry.context.Context;
+import redis.RedisCommand;
import scala.runtime.AbstractFunction1;
import scala.util.Try;
-public class OnCompleteHandler extends AbstractFunction1<Try<Object>, Void> {
+public final class OnCompleteHandler extends AbstractFunction1<Try<Object>, Void> {
private final Context context;
+ private final RedisCommand<?, ?> request;
- public OnCompleteHandler(Context context) {
+ public OnCompleteHandler(Context context, RedisCommand<?, ?> request) {
this.context = context;
+ this.request = request;
}
@Override
public Void apply(Try<Object> result) {
+ Throwable error = null;
if (result.isFailure()) {
- tracer().endExceptionally(context, result.failed().get());
- } else {
- tracer().end(context);
+ error = result.failed().get();
}
+ instrumenter().end(context, request, null, error);
return null;
}
}

ADD
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaAttributesExtractor.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rediscala;
+
+import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
+import io.opentelemetry.instrumentation.api.tracer.ClassNames;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import java.util.Locale;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import redis.RedisCommand;
+
+final class RediscalaAttributesExtractor extends DbAttributesExtractor<RedisCommand<?, ?>, Void> {
+ @Override
+ protected String system(RedisCommand<?, ?> redisCommand) {
+ return SemanticAttributes.DbSystemValues.REDIS;
+ }
+
+ @Override
+ protected @Nullable String user(RedisCommand<?, ?> redisCommand) {
+ return null;
+ }
+
+ @Override
+ protected @Nullable String name(RedisCommand<?, ?> redisCommand) {
+ return null;
+ }
+
+ @Override
+ protected @Nullable String connectionString(RedisCommand<?, ?> redisCommand) {
+ return null;
+ }
+
+ @Override
+ protected @Nullable String statement(RedisCommand<?, ?> redisCommand) {
+ return null;
+ }
+
+ @Override
+ protected String operation(RedisCommand<?, ?> redisCommand) {
+ return ClassNames.simpleName(redisCommand.getClass()).toUpperCase(Locale.ROOT);
+ }
+}

DELETE
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.rediscala;
-
-import io.opentelemetry.instrumentation.api.tracer.ClassNames;
-import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer;
-import io.opentelemetry.instrumentation.api.tracer.net.NetPeerAttributes;
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DbSystemValues;
-import java.net.InetSocketAddress;
-import redis.RedisCommand;
-
-public class RediscalaClientTracer
- extends DatabaseClientTracer<RedisCommand<?, ?>, RedisCommand<?, ?>, String> {
-
- private static final RediscalaClientTracer TRACER = new RediscalaClientTracer();
-
- private RediscalaClientTracer() {
- super(NetPeerAttributes.INSTANCE);
- }
-
- public static RediscalaClientTracer tracer() {
- return TRACER;
- }
-
- @Override
- protected String sanitizeStatement(RedisCommand<?, ?> redisCommand) {
- return ClassNames.simpleName(redisCommand.getClass());
- }
-
- @Override
- protected String spanName(
- RedisCommand<?, ?> connection, RedisCommand<?, ?> statement, String operation) {
- return operation;
- }
-
- @Override
- protected String dbSystem(RedisCommand<?, ?> redisCommand) {
- return DbSystemValues.REDIS;
- }
-
- @Override
- protected InetSocketAddress peerAddress(RedisCommand<?, ?> redisCommand) {
- return null;
- }
-
- @Override
- protected String dbStatement(
- RedisCommand<?, ?> connection, RedisCommand<?, ?> command, String operation) {
- return operation;
- }
-
- @Override
- protected String getInstrumentationName() {
- return "io.opentelemetry.rediscala-1.8";
- }
-}

ADD
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaSingletons.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rediscala;
+
+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.DbSpanNameExtractor;
+import redis.RedisCommand;
+
+public final class RediscalaSingletons {
+
+ private static final String INSTRUMENTATION_NAME = "io.opentelemetry.rediscala-1.8";
+
+ private static final Instrumenter<RedisCommand<?, ?>, Void> INSTRUMENTER;
+
+ static {
+ RediscalaAttributesExtractor attributesExtractor = new RediscalaAttributesExtractor();
+ SpanNameExtractor<RedisCommand<?, ?>> spanNameExtractor =
+ DbSpanNameExtractor.create(attributesExtractor);
+
+ INSTRUMENTER =
+ Instrumenter.<RedisCommand<?, ?>, Void>newBuilder(
+ GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor)
+ .addAttributesExtractor(attributesExtractor)
+ .newInstrumenter(SpanKindExtractor.alwaysClient());
+ }
+
+ public static Instrumenter<RedisCommand<?, ?>, Void> instrumenter() {
+ return INSTRUMENTER;
+ }
+
+ private RediscalaSingletons() {}
+}

MODIFY
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java
instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java
@@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.rediscala;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasSuperType;
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
-import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaClientTracer.tracer;
+import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -62,23 +62,34 @@ public class RequestInstrumentation implements TypeInstrumentation {
@Advice.Argument(0) RedisCommand<?, ?> cmd,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
- context = tracer().startSpan(currentContext(), cmd, cmd);
+
+ Context parentContext = currentContext();
+ if (!instrumenter().shouldStart(parentContext, cmd)) {
+ return;
+ }
+
+ context = instrumenter().start(parentContext, cmd);
scope = context.makeCurrent();
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
- public static void stopSpan(
+ public static void onExit(
+ @Advice.Argument(0) RedisCommand<?, ?> cmd,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope,
@Advice.Thrown Throwable throwable,
@Advice.FieldValue("executionContext") ExecutionContext ctx,
@Advice.Return(readOnly = false) Future<Object> responseFuture) {
+
+ if (scope == null) {
+ return;
+ }
scope.close();
if (throwable != null) {
- tracer().endExceptionally(context, throwable);
+ instrumenter().end(context, cmd, null, throwable);
} else {
- responseFuture.onComplete(new OnCompleteHandler(context), ctx);
+ responseFuture.onComplete(new OnCompleteHandler(context, cmd), ctx);
}
}
}

MODIFY
instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy
instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy
@@ -66,11 +66,11 @@ class RediscalaClientTest extends AgentInstrumentationSpecification {
assertTraces(1) {
trace(0, 1) {
span(0) {
- name "Set"
+ name "SET"
kind CLIENT
attributes {
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
- "${SemanticAttributes.DB_STATEMENT.key}" "Set"
+ "${SemanticAttributes.DB_OPERATION.key}" "SET"
}
}
}
@@ -79,36 +79,42 @@ class RediscalaClientTest extends AgentInstrumentationSpecification {
def "get command"() {
when:
- def write = redisClient.set("bar",
+ def (write, value) = runWithSpan("parent") {
+ def w = redisClient.set("bar",
"baz",
Option.apply(null),
Option.apply(null),
false,
false,
new ByteStringSerializerLowPriority.String$())
- def value = redisClient.get("bar", new ByteStringDeserializerDefault.String$())
+ def v = redisClient.get("bar", new ByteStringDeserializerDefault.String$())
+ return new Tuple(w, v)
+ }
then:
Await.result(write, Duration.apply("3 second")) == true
Await.result(value, Duration.apply("3 second")) == Option.apply("baz")
- assertTraces(2) {
- trace(0, 1) {
+ assertTraces(1) {
+ trace(0, 3) {
span(0) {
- name "Set"
+ name "parent"
+ }
+ span(1) {
+ name "SET"
kind CLIENT
+ childOf span(0)
attributes {
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
- "${SemanticAttributes.DB_STATEMENT.key}" "Set"
- }
+ "${SemanticAttributes.DB_OPERATION.key}" "SET"
}
}
- trace(1, 1) {
- span(0) {
- name "Get"
+ span(2) {
+ name "GET"
kind CLIENT
+ childOf span(0)
attributes {
"${SemanticAttributes.DB_SYSTEM.key}" "redis"
- "${SemanticAttributes.DB_STATEMENT.key}" "Get"
+ "${SemanticAttributes.DB_OPERATION.key}" "GET"
}
}
}

Convert Rediscala to Instrumenter API (#4152)