Migrate RMI instrumentation to Instrumenter API (#4579)

This commit is contained in:
Mateusz Rzeszutek 2021-11-04 16:54:34 +01:00 committed by GitHub
parent a7e3696176
commit a9ed1ae030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 196 additions and 131 deletions

View File

@ -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"))
}

View File

@ -0,0 +1,27 @@
/*
* 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();
}
}

View File

@ -0,0 +1,35 @@
/*
* 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() {}
}

View File

@ -1,47 +0,0 @@
/*
* 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";
}
}

View File

@ -6,7 +6,7 @@
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;
}
context = tracer().startSpan(method);
if (!instrumenter().shouldStart(parentContext, method)) {
return;
}
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);
}
}
}

View File

@ -5,8 +5,7 @@
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);
}
}
}

View File

@ -6,10 +6,8 @@
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);

View File

@ -0,0 +1,20 @@
/*
* 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();
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,26 @@
/*
* 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();
}
}

View File

@ -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");
}

View File

@ -0,0 +1,34 @@
/*
* 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() {}
}

View File

@ -1,45 +0,0 @@
/*
* 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";
}
}