Migrate external-annotations instrumentation to Instrumenter API
MODIFY
instrumentation/external-annotations/javaagent/build.gradle.kts
instrumentation/external-annotations/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(":javaagent-tooling"))
testImplementation("com.newrelic.agent.java:newrelic-api:5.14.0")

ADD
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ClassAndMethod.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.extannotations;
+
+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();
+}

ADD
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationAttributesExtractor.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.extannotations;
+
+import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesExtractor;
+import javax.annotation.Nullable;
+
+final class ExternalAnnotationAttributesExtractor
+ extends CodeAttributesExtractor<ClassAndMethod, Void> {
+
+ @Override
+ protected Class<?> codeClass(ClassAndMethod classAndMethod) {
+ return classAndMethod.declaringClass();
+ }
+
+ @Override
+ protected String methodName(ClassAndMethod classAndMethod) {
+ return classAndMethod.methodName();
+ }
+
+ @Nullable
+ @Override
+ protected String filePath(ClassAndMethod classAndMethod) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ protected Long lineNumber(ClassAndMethod classAndMethod) {
+ return null;
+ }
+}

MODIFY
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java
@@ -7,7 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.extannotations;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasSuperType;
-import static io.opentelemetry.javaagent.instrumentation.extannotations.ExternalAnnotationTracer.tracer;
+import static io.opentelemetry.javaagent.instrumentation.extannotations.ExternalAnnotationSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
@@ -20,8 +20,8 @@ import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
+import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser;
-import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -163,24 +163,34 @@ public class ExternalAnnotationInstrumentation 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("otelRequest") ClassAndMethod request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
- context = tracer().startSpan(method);
+
+ Context parentContext = Java8BytecodeBridge.currentContext();
+ request = ClassAndMethod.create(declaringClass, methodName);
+ if (!instrumenter().shouldStart(parentContext, request)) {
+ return;
+ }
+
+ context = instrumenter().start(parentContext, request);
scope = context.makeCurrent();
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan(
+ @Advice.Local("otelRequest") ClassAndMethod request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope,
@Advice.Thrown Throwable throwable) {
- scope.close();
- if (throwable != null) {
- tracer().endExceptionally(context, throwable);
- } else {
- tracer().end(context);
+
+ if (scope == null) {
+ return;
}
+ scope.close();
+ instrumenter().end(context, request, null, throwable);
}
}
}

ADD
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationSingletons.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.extannotations;
+
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
+import io.opentelemetry.instrumentation.api.instrumenter.code.CodeSpanNameExtractor;
+
+public final class ExternalAnnotationSingletons {
+
+ private static final Instrumenter<ClassAndMethod, Void> INSTRUMENTER;
+
+ static {
+ ExternalAnnotationAttributesExtractor attributesExtractor =
+ new ExternalAnnotationAttributesExtractor();
+
+ INSTRUMENTER =
+ Instrumenter.<ClassAndMethod, Void>builder(
+ GlobalOpenTelemetry.get(),
+ "io.opentelemetry.external-annotations",
+ CodeSpanNameExtractor.create(attributesExtractor))
+ .addAttributesExtractor(attributesExtractor)
+ .newInstrumenter();
+ }
+
+ public static Instrumenter<ClassAndMethod, Void> instrumenter() {
+ return INSTRUMENTER;
+ }
+
+ private ExternalAnnotationSingletons() {}
+}

DELETE
instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationTracer.java
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.extannotations;
-
-import io.opentelemetry.context.Context;
-import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
-import io.opentelemetry.instrumentation.api.tracer.SpanNames;
-import java.lang.reflect.Method;
-
-public class ExternalAnnotationTracer extends BaseTracer {
- private static final ExternalAnnotationTracer TRACER = new ExternalAnnotationTracer();
-
- public static ExternalAnnotationTracer tracer() {
- return TRACER;
- }
-
- @Override
- protected String getInstrumentationName() {
- return "io.opentelemetry.external-annotations";
- }
-
- public Context startSpan(Method method) {
- return startSpan(SpanNames.fromMethod(method));
- }
-}

MODIFY
instrumentation/external-annotations/javaagent/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy
instrumentation/external-annotations/javaagent/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.opentelemetry.test.annotation.SayTracedHello
import java.util.concurrent.Callable
@@ -28,6 +29,8 @@ class ConfiguredTraceAnnotationsTest extends AgentInstrumentationSpecification {
span(0) {
name "AnnotationTracedCallable.call"
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" AnnotationTracedCallable.name
+ "${SemanticAttributes.CODE_FUNCTION}" "call"
}
}
}

MODIFY
instrumentation/external-annotations/javaagent/src/test/groovy/TraceAnnotationsTest.groovy
instrumentation/external-annotations/javaagent/src/test/groovy/TraceAnnotationsTest.groovy
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.opentelemetry.test.annotation.SayTracedHello
import io.opentracing.contrib.dropwizard.Trace
@@ -25,6 +26,8 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
name "SayTracedHello.sayHello"
hasNoParent()
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "sayHello"
"myattr" "test"
}
}
@@ -44,6 +47,8 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
name "SayTracedHello.sayHelloSayHa"
hasNoParent()
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "sayHelloSayHa"
"myattr" "test2"
}
}
@@ -51,6 +56,8 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
name "SayTracedHello.sayHello"
childOf span(0)
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "sayHello"
"myattr" "test"
}
}
@@ -58,6 +65,8 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
name "SayTracedHello.sayHello"
childOf span(0)
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "sayHello"
"myattr" "test"
}
}
@@ -81,6 +90,10 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
name "SayTracedHello.sayError"
status ERROR
errorEvent(error.class)
+ attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "sayError"
+ }
}
}
}
@@ -97,6 +110,8 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
span(0) {
name "SayTracedHello\$1.call"
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name + '$1'
+ "${SemanticAttributes.CODE_FUNCTION}" "call"
}
}
}
@@ -118,12 +133,16 @@ class TraceAnnotationsTest extends AgentInstrumentationSpecification {
span(0) {
name "SayTracedHello\$1.call"
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name + '$1'
+ "${SemanticAttributes.CODE_FUNCTION}" "call"
}
}
trace(1, 1) {
span(0) {
name "TraceAnnotationsTest\$1.call"
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" TraceAnnotationsTest.name + '$1'
+ "${SemanticAttributes.CODE_FUNCTION}" "call"
}
}
}

MODIFY
instrumentation/external-annotations/javaagent/src/test/groovy/TraceProvidersTest.groovy
instrumentation/external-annotations/javaagent/src/test/groovy/TraceProvidersTest.groovy
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.opentelemetry.test.annotation.SayTracedHello
/**
@@ -22,6 +23,8 @@ class TraceProvidersTest extends AgentInstrumentationSpecification {
name "SayTracedHello.${provider.toLowerCase()}"
hasNoParent()
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" SayTracedHello.name
+ "${SemanticAttributes.CODE_FUNCTION}" "${provider.toLowerCase()}"
"providerAttr" provider
}
}

MODIFY
instrumentation/external-annotations/javaagent/src/test/groovy/TracedMethodsExclusionTest.groovy
instrumentation/external-annotations/javaagent/src/test/groovy/TracedMethodsExclusionTest.groovy
*/
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import io.opentracing.contrib.dropwizard.Trace
class TracedMethodsExclusionTest extends AgentInstrumentationSpecification {
@@ -45,6 +46,8 @@ class TracedMethodsExclusionTest extends AgentInstrumentationSpecification {
span(0) {
name "TestClass.annotated"
attributes {
+ "${SemanticAttributes.CODE_NAMESPACE}" TestClass.name
+ "${SemanticAttributes.CODE_FUNCTION}" "annotated"
}
}
}

Migrate external-annotations instrumentation to Instrumenter API (#4578)