Migrate RMI instrumentation to Instrumenter API
MODIFY
instrumentation/rmi/javaagent/build.gradle.kts
instrumentation/rmi/javaagent/build.gradle.kts
@@ -9,6 +9,9 @@ muzzle {
}
dependencies {
+ compileOnly("com.google.auto.value:auto-value-annotations")
+ annotationProcessor("com.google.auto.value:auto-value")
+
compileOnly(project(":instrumentation:rmi:bootstrap"))
}

ADD
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientAttributesExtractor.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rmi.client;
+
+import io.opentelemetry.instrumentation.api.instrumenter.rpc.RpcAttributesExtractor;
+import java.lang.reflect.Method;
+
+final class RmiClientAttributesExtractor extends RpcAttributesExtractor<Method, Void> {
+
+ @Override
+ protected String system(Method method) {
+ return "java_rmi";
+ }
+
+ @Override
+ protected String service(Method method) {
+ return method.getDeclaringClass().getName();
+ }
+
+ @Override
+ protected String method(Method method) {
+ return method.getName();
+ }
+}

ADD
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientSingletons.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rmi.client;
+
+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.rpc.RpcSpanNameExtractor;
+import java.lang.reflect.Method;
+
+public final class RmiClientSingletons {
+
+ private static final Instrumenter<Method, Void> INSTRUMENTER;
+
+ static {
+ RmiClientAttributesExtractor attributesExtractor = new RmiClientAttributesExtractor();
+
+ INSTRUMENTER =
+ Instrumenter.<Method, Void>builder(
+ GlobalOpenTelemetry.get(),
+ "io.opentelemetry.rmi",
+ RpcSpanNameExtractor.create(attributesExtractor))
+ .addAttributesExtractor(attributesExtractor)
+ .newInstrumenter(SpanKindExtractor.alwaysClient());
+ }
+
+ public static Instrumenter<Method, Void> instrumenter() {
+ return INSTRUMENTER;
+ }
+
+ private RmiClientSingletons() {}
+}

DELETE
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.rmi.client;
-
-import static io.opentelemetry.api.trace.SpanKind.CLIENT;
-
-import io.opentelemetry.api.trace.Span;
-import io.opentelemetry.context.Context;
-import io.opentelemetry.instrumentation.api.tracer.RpcClientTracer;
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
-import java.lang.reflect.Method;
-
-public class RmiClientTracer extends RpcClientTracer {
- private static final RmiClientTracer TRACER = new RmiClientTracer();
-
- public static RmiClientTracer tracer() {
- return TRACER;
- }
-
- public Context startSpan(Method method) {
- Context parentContext = Context.current();
- String serviceName = method.getDeclaringClass().getName();
- String methodName = method.getName();
-
- Span span =
- spanBuilder(parentContext, serviceName + "/" + methodName, CLIENT)
- .setAttribute(SemanticAttributes.RPC_SYSTEM, getRpcSystem())
- .setAttribute(SemanticAttributes.RPC_SERVICE, serviceName)
- .setAttribute(SemanticAttributes.RPC_METHOD, methodName)
- .startSpan();
-
- return parentContext.with(span);
- }
-
- @Override
- protected String getInstrumentationName() {
- return "io.opentelemetry.rmi";
- }
-
- @Override
- protected String getRpcSystem() {
- return "java_rmi";
- }
-}

MODIFY
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/UnicastRefInstrumentation.java
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/UnicastRefInstrumentation.java
package io.opentelemetry.javaagent.instrumentation.rmi.client;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
-import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientTracer.tracer;
+import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@@ -46,28 +46,33 @@ public class UnicastRefInstrumentation implements TypeInstrumentation {
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
- // TODO replace with client span check
- if (!Java8BytecodeBridge.currentSpan().getSpanContext().isValid()) {
+ Context parentContext = Java8BytecodeBridge.currentContext();
+
+ // TODO replace with client span check - this is a bit different condition though, can we
+ // remove it?
+ if (!Java8BytecodeBridge.spanFromContext(parentContext).getSpanContext().isValid()) {
+ return;
+ }
+ if (!instrumenter().shouldStart(parentContext, method)) {
return;
}
- context = tracer().startSpan(method);
+
+ context = instrumenter().start(parentContext, method);
scope = context.makeCurrent();
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan(
+ @Advice.Argument(value = 1) Method method,
@Advice.Thrown Throwable throwable,
@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);
- }
+ instrumenter().end(context, method, null, throwable);
}
}
}

MODIFY
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPayload.java
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPayload.java
package io.opentelemetry.javaagent.instrumentation.rmi.context;
-import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientTracer.tracer;
-
+import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapSetter;
@@ -24,11 +23,9 @@ public class ContextPayload {
private static final Logger logger = LoggerFactory.getLogger(ContextPayload.class);
private final Map<String, String> context;
- public static final ExtractAdapter GETTER = new ExtractAdapter();
- public static final ContextPayloadSetter SETTER = ContextPayloadSetter.INSTANCE;
public ContextPayload() {
- context = new HashMap<>();
+ this(new HashMap<>());
}
public ContextPayload(Map<String, String> context) {
@@ -37,7 +34,9 @@ public class ContextPayload {
public static ContextPayload from(Context context) {
ContextPayload payload = new ContextPayload();
- tracer().inject(context, payload, SETTER);
+ GlobalOpenTelemetry.getPropagators()
+ .getTextMapPropagator()
+ .inject(context, payload, ContextPayloadSetter.INSTANCE);
return payload;
}
@@ -54,32 +53,36 @@ public class ContextPayload {
return null;
}
- public Map<String, String> getSpanContext() {
- return context;
- }
-
public void write(ObjectOutput out) throws IOException {
out.writeObject(context);
}
- public static class ExtractAdapter implements TextMapGetter<ContextPayload> {
+ public Context extract() {
+ return GlobalOpenTelemetry.getPropagators()
+ .getTextMapPropagator()
+ .extract(Context.root(), this, ContextPayloadGetter.INSTANCE);
+ }
+
+ private enum ContextPayloadGetter implements TextMapGetter<ContextPayload> {
+ INSTANCE;
+
@Override
public Iterable<String> keys(ContextPayload contextPayload) {
- return contextPayload.getSpanContext().keySet();
+ return contextPayload.context.keySet();
}
@Override
public String get(ContextPayload carrier, String key) {
- return carrier.getSpanContext().get(key);
+ return carrier.context.get(key);
}
}
- enum ContextPayloadSetter implements TextMapSetter<ContextPayload> {
+ private enum ContextPayloadSetter implements TextMapSetter<ContextPayload> {
INSTANCE;
@Override
public void set(ContextPayload carrier, String key, String value) {
- carrier.getSpanContext().put(key, value);
+ carrier.context.put(key, value);
}
}
}

MODIFY
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/ContextDispatcher.java
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/ContextDispatcher.java
package io.opentelemetry.javaagent.instrumentation.rmi.context.server;
import static io.opentelemetry.javaagent.bootstrap.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT;
-import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload.GETTER;
import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.CONTEXT_CALL_ID;
import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.PROPAGATOR;
-import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerTracer.tracer;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
@@ -51,7 +49,7 @@ public class ContextDispatcher implements Dispatcher {
if (PROPAGATOR.isOperationWithPayload(operationId)) {
ContextPayload payload = ContextPayload.read(in);
if (payload != null) {
- Context context = tracer().extract(payload, GETTER);
+ Context context = payload.extract();
SpanContext spanContext = Span.fromContext(context).getSpanContext();
if (spanContext.isValid()) {
THREAD_LOCAL_CONTEXT.set(context);

ADD
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/ClassAndMethod.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rmi.server;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class ClassAndMethod {
+
+ public static ClassAndMethod create(Class<?> declaringClass, String methodName) {
+ return new AutoValue_ClassAndMethod(declaringClass, methodName);
+ }
+
+ public abstract Class<?> declaringClass();
+
+ public abstract String methodName();
+}

MODIFY
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RemoteServerInstrumentation.java
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RemoteServerInstrumentation.java
@@ -7,7 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.rmi.server;
import static io.opentelemetry.javaagent.bootstrap.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.extendsClass;
-import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerTracer.tracer;
+import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
@@ -19,7 +19,6 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.CallDepth;
-import java.lang.reflect.Method;
import java.rmi.server.RemoteServer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
@@ -43,10 +42,13 @@ public class RemoteServerInstrumentation implements TypeInstrumentation {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onEnter(
- @Advice.Origin Method method,
+ @Advice.Origin("#t") Class<?> declaringClass,
+ @Advice.Origin("#m") String methodName,
@Advice.Local("otelCallDepth") CallDepth callDepth,
+ @Advice.Local("otelRequest") ClassAndMethod request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
+
callDepth = CallDepth.forClass(RemoteServer.class);
if (callDepth.getAndIncrement() > 0) {
return;
@@ -54,8 +56,12 @@ public class RemoteServerInstrumentation implements TypeInstrumentation {
// TODO review and unify with all other SERVER instrumentation
Context parentContext = THREAD_LOCAL_CONTEXT.getAndResetContext();
+ request = ClassAndMethod.create(declaringClass, methodName);
+ if (!instrumenter().shouldStart(parentContext, request)) {
+ return;
+ }
- context = tracer().startSpan(parentContext, method);
+ context = instrumenter().start(parentContext, request);
scope = context.makeCurrent();
}
@@ -63,18 +69,18 @@ public class RemoteServerInstrumentation implements TypeInstrumentation {
public static void stopSpan(
@Advice.Thrown Throwable throwable,
@Advice.Local("otelCallDepth") CallDepth callDepth,
+ @Advice.Local("otelRequest") ClassAndMethod request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
+
if (callDepth.decrementAndGet() > 0) {
return;
}
-
- scope.close();
- if (throwable != null) {
- RmiServerTracer.tracer().endExceptionally(context, throwable);
- } else {
- RmiServerTracer.tracer().end(context);
+ if (scope == null) {
+ return;
}
+ scope.close();
+ instrumenter().end(context, request, null, throwable);
}
}
}

ADD
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerAttributesExtractor.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rmi.server;
+
+import io.opentelemetry.instrumentation.api.instrumenter.rpc.RpcAttributesExtractor;
+
+final class RmiServerAttributesExtractor extends RpcAttributesExtractor<ClassAndMethod, Void> {
+
+ @Override
+ protected String system(ClassAndMethod classAndMethod) {
+ return "java_rmi";
+ }
+
+ @Override
+ protected String service(ClassAndMethod classAndMethod) {
+ return classAndMethod.declaringClass().getName();
+ }
+
+ @Override
+ protected String method(ClassAndMethod classAndMethod) {
+ return classAndMethod.methodName();
+ }
+}

RENAME
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentationModule.java
@@ -13,9 +13,9 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import java.util.List;
@AutoService(InstrumentationModule.class)
-public class RmiServerInstrumentation extends InstrumentationModule {
+public class RmiServerInstrumentationModule extends InstrumentationModule {
- public RmiServerInstrumentation() {
+ public RmiServerInstrumentationModule() {
super("rmi", "rmi-server");
}

ADD
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerSingletons.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.rmi.server;
+
+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.rpc.RpcSpanNameExtractor;
+
+public final class RmiServerSingletons {
+
+ private static final Instrumenter<ClassAndMethod, Void> INSTRUMENTER;
+
+ static {
+ RmiServerAttributesExtractor attributesExtractor = new RmiServerAttributesExtractor();
+
+ INSTRUMENTER =
+ Instrumenter.<ClassAndMethod, Void>builder(
+ GlobalOpenTelemetry.get(),
+ "io.opentelemetry.rmi",
+ RpcSpanNameExtractor.create(attributesExtractor))
+ .addAttributesExtractor(attributesExtractor)
+ .newInstrumenter(SpanKindExtractor.alwaysServer());
+ }
+
+ public static Instrumenter<ClassAndMethod, Void> instrumenter() {
+ return INSTRUMENTER;
+ }
+
+ private RmiServerSingletons() {}
+}

DELETE
instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.rmi.server;
-
-import static io.opentelemetry.api.trace.SpanKind.SERVER;
-
-import io.opentelemetry.api.trace.SpanBuilder;
-import io.opentelemetry.context.Context;
-import io.opentelemetry.context.propagation.TextMapGetter;
-import io.opentelemetry.instrumentation.api.tracer.RpcServerTracer;
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
-import java.lang.reflect.Method;
-
-public class RmiServerTracer extends RpcServerTracer {
- private static final RmiServerTracer TRACER = new RmiServerTracer();
-
- public static RmiServerTracer tracer() {
- return TRACER;
- }
-
- public Context startSpan(Context parentContext, Method method) {
- String serviceName = method.getDeclaringClass().getName();
- String methodName = method.getName();
-
- SpanBuilder spanBuilder =
- spanBuilder(parentContext, serviceName + "/" + methodName, SERVER)
- .setAttribute(SemanticAttributes.RPC_SYSTEM, "java_rmi")
- .setAttribute(SemanticAttributes.RPC_SERVICE, serviceName)
- .setAttribute(SemanticAttributes.RPC_METHOD, methodName);
- return parentContext.with(spanBuilder.startSpan());
- }
-
- @Override
- protected TextMapGetter getGetter() {
- return null;
- }
-
- @Override
- protected String getInstrumentationName() {
- return "io.opentelemetry.rmi";
- }
-}

Migrate RMI instrumentation to Instrumenter API (#4579)