Update methods-javaagent to Instrumenter API (#3070)
* Update methods-javaagent to Instrumenter API Signed-off-by: dengliming <liming.d.pro@gmail.com> * introduce SpanNames Signed-off-by: dengliming <liming.d.pro@gmail.com> * Add test for SpanNames Signed-off-by: dengliming <liming.d.pro@gmail.com> * Fix merge * Codenarc * Remove unused dep Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
parent
b5f949afb2
commit
ca5b792f95
|
@ -181,43 +181,45 @@ public abstract class BaseTracer {
|
||||||
/**
|
/**
|
||||||
* This method is used to generate an acceptable span (operation) name based on a given method
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
* reference. Anonymous classes are named based on their parent.
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link SpanNames#spanNameForMethod(Method)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String spanNameForMethod(Method method) {
|
public static String spanNameForMethod(Method method) {
|
||||||
return spanNameForMethod(method.getDeclaringClass(), method.getName());
|
return SpanNames.spanNameForMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to generate an acceptable span (operation) name based on a given method
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
* reference. Anonymous classes are named based on their parent.
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link SpanNames#spanNameForMethod(Class, Method)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String spanNameForMethod(Class<?> clazz, @Nullable Method method) {
|
public static String spanNameForMethod(Class<?> clazz, @Nullable Method method) {
|
||||||
return spanNameForMethod(clazz, method == null ? "<unknown>" : method.getName());
|
return SpanNames.spanNameForMethod(clazz, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to generate an acceptable span (operation) name based on a given method
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
* reference. Anonymous classes are named based on their parent.
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link SpanNames#spanNameForMethod(Class, String)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String spanNameForMethod(Class<?> cl, String methodName) {
|
public static String spanNameForMethod(Class<?> cl, String methodName) {
|
||||||
return spanNameForClass(cl) + "." + methodName;
|
return SpanNames.spanNameForMethod(cl, methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to generate an acceptable span (operation) name based on a given class
|
* This method is used to generate an acceptable span (operation) name based on a given class
|
||||||
* reference. Anonymous classes are named based on their parent.
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link SpanNames#spanNameForClass(Class)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static String spanNameForClass(Class<?> clazz) {
|
public static String spanNameForClass(Class<?> clazz) {
|
||||||
if (!clazz.isAnonymousClass()) {
|
return SpanNames.spanNameForClass(clazz);
|
||||||
return clazz.getSimpleName();
|
|
||||||
}
|
|
||||||
String className = clazz.getName();
|
|
||||||
if (clazz.getPackage() != null) {
|
|
||||||
String pkgName = clazz.getPackage().getName();
|
|
||||||
if (!pkgName.isEmpty()) {
|
|
||||||
className = className.substring(pkgName.length() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return className;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ends the execution of a span stored in the passed {@code context}. */
|
/** Ends the execution of a span stored in the passed {@code context}. */
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.api.tracer;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
public final class SpanNames {
|
||||||
|
/**
|
||||||
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*/
|
||||||
|
public static String spanNameForMethod(Method method) {
|
||||||
|
return spanNameForMethod(method.getDeclaringClass(), method.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*/
|
||||||
|
public static String spanNameForMethod(Class<?> clazz, @Nullable Method method) {
|
||||||
|
return spanNameForMethod(clazz, method == null ? "<unknown>" : method.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to generate an acceptable span (operation) name based on a given method
|
||||||
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*/
|
||||||
|
public static String spanNameForMethod(Class<?> cl, String methodName) {
|
||||||
|
return spanNameForClass(cl) + "." + methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to generate an acceptable span (operation) name based on a given class
|
||||||
|
* reference. Anonymous classes are named based on their parent.
|
||||||
|
*/
|
||||||
|
public static String spanNameForClass(Class<?> clazz) {
|
||||||
|
if (!clazz.isAnonymousClass()) {
|
||||||
|
return clazz.getSimpleName();
|
||||||
|
}
|
||||||
|
String className = clazz.getName();
|
||||||
|
if (clazz.getPackage() != null) {
|
||||||
|
String pkgName = clazz.getPackage().getName();
|
||||||
|
if (!pkgName.isEmpty()) {
|
||||||
|
className = className.substring(pkgName.length() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpanNames() {}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.api.tracer
|
||||||
|
|
||||||
|
import org.spockframework.util.ReflectionUtil
|
||||||
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
class SpanNamesTest extends Specification {
|
||||||
|
|
||||||
|
def "test spanNameForClass"() {
|
||||||
|
when:
|
||||||
|
String result = SpanNames.spanNameForClass(clazz)
|
||||||
|
|
||||||
|
then:
|
||||||
|
result == expected
|
||||||
|
|
||||||
|
where:
|
||||||
|
clazz | expected
|
||||||
|
SpanNamesTest | "SpanNamesTest"
|
||||||
|
SpanNames | "SpanNames"
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test spanNameForMethod"() {
|
||||||
|
when:
|
||||||
|
String result = SpanNames.spanNameForMethod(method)
|
||||||
|
|
||||||
|
then:
|
||||||
|
result == expected
|
||||||
|
|
||||||
|
where:
|
||||||
|
method | expected
|
||||||
|
ReflectionUtil.getMethodByName(SpanNames, "spanNameForClass") | "SpanNames.spanNameForClass"
|
||||||
|
ReflectionUtil.getMethodByName(String, "length") | "String.length"
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test spanNameForMethod with class"() {
|
||||||
|
when:
|
||||||
|
String result = SpanNames.spanNameForMethod(clazz, method)
|
||||||
|
|
||||||
|
then:
|
||||||
|
result == expected
|
||||||
|
|
||||||
|
where:
|
||||||
|
clazz | method | expected
|
||||||
|
SpanNames | ReflectionUtil.getMethodByName(SpanNames, "spanNameForClass") | "SpanNames.spanNameForClass"
|
||||||
|
SpanNames | "test" | "SpanNames.test"
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,8 @@ package io.opentelemetry.javaagent.instrumentation.methods;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.safeHasSuperType;
|
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.safeHasSuperType;
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
||||||
import static io.opentelemetry.javaagent.instrumentation.methods.MethodTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
|
||||||
|
import static io.opentelemetry.javaagent.instrumentation.methods.MethodInstrumenters.instrumenter;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
|
@ -62,21 +63,23 @@ public class MethodInstrumentation implements TypeInstrumentation {
|
||||||
@Advice.Origin Method method,
|
@Advice.Origin Method method,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
context = tracer().startSpan(method);
|
Context parentContext = currentContext();
|
||||||
|
if (!instrumenter().shouldStart(parentContext, method)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = instrumenter().start(parentContext, method);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void stopSpan(
|
public static void stopSpan(
|
||||||
|
@Advice.Origin Method method,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope,
|
@Advice.Local("otelScope") Scope scope,
|
||||||
@Advice.Thrown Throwable throwable) {
|
@Advice.Thrown Throwable throwable) {
|
||||||
scope.close();
|
scope.close();
|
||||||
if (throwable != null) {
|
instrumenter().end(context, method, null, throwable);
|
||||||
tracer().endExceptionally(context, throwable);
|
|
||||||
} else {
|
|
||||||
tracer().end(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class MethodInstrumentationModule extends InstrumentationModule {
|
||||||
public List<String> getMuzzleHelperClassNames() {
|
public List<String> getMuzzleHelperClassNames() {
|
||||||
return typeInstrumentations.isEmpty()
|
return typeInstrumentations.isEmpty()
|
||||||
? emptyList()
|
? emptyList()
|
||||||
: singletonList("io.opentelemetry.javaagent.instrumentation.methods.MethodTracer");
|
: singletonList("io.opentelemetry.javaagent.instrumentation.methods.MethodInstrumenters");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.methods;
|
||||||
|
|
||||||
|
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.tracer.SpanNames;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public final class MethodInstrumenters {
|
||||||
|
private static final String INSTRUMENTATION_NAME =
|
||||||
|
"io.opentelemetry.javaagent.external-annotations";
|
||||||
|
|
||||||
|
private static final Instrumenter<Method, Void> INSTRUMENTER;
|
||||||
|
|
||||||
|
static {
|
||||||
|
SpanNameExtractor<Method> spanName = SpanNames::spanNameForMethod;
|
||||||
|
|
||||||
|
INSTRUMENTER =
|
||||||
|
Instrumenter.<Method, Void>newBuilder(
|
||||||
|
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanName)
|
||||||
|
.newInstrumenter(SpanKindExtractor.alwaysInternal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Instrumenter<Method, Void> instrumenter() {
|
||||||
|
return INSTRUMENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodInstrumenters() {}
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.methods;
|
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
|
||||||
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
public class MethodTracer extends BaseTracer {
|
|
||||||
private static final MethodTracer TRACER = new MethodTracer();
|
|
||||||
|
|
||||||
public static MethodTracer tracer() {
|
|
||||||
return TRACER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getInstrumentationName() {
|
|
||||||
return "io.opentelemetry.javaagent.external-annotations";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context startSpan(Method method) {
|
|
||||||
return startSpan(spanNameForMethod(method));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue