From e76042920603cc6cce5ca35a87ef0da10bedfeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kleszcz?= Date: Wed, 29 Oct 2025 10:41:49 +0100 Subject: [PATCH 1/3] Add instrumentation for otel span annotations --- gradle/libs.versions.toml | 1 + instrumentation/span-annotation/README.md | 1 + .../span-annotation/agent/build.gradle.kts | 18 +++ .../spanannotation/SpanAnnotationPlugin.kt | 116 ++++++++++++++++++ .../AddingSpanAttributesConstructorAdvice.kt | 18 +++ .../SpanAttributeConstructorAdvice.kt | 23 ++++ .../constructor/WithSpanConstructorAdvice.kt | 30 +++++ .../AddingSpanAttributesMethodAdvice.kt | 22 ++++ .../method/SpanAttributeMethodAdvice.kt | 23 ++++ .../advice/method/WithSpanMethodAdvice.kt | 37 ++++++ .../META-INF/net.bytebuddy/build.plugins | 1 + .../span-annotation/library/build.gradle.kts | 17 +++ .../library/spanannotation/HelperFunctions.kt | 59 +++++++++ .../SpanAnnotationInstrumentation.kt | 23 ++++ 14 files changed, 389 insertions(+) create mode 100644 instrumentation/span-annotation/README.md create mode 100644 instrumentation/span-annotation/agent/build.gradle.kts create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt create mode 100644 instrumentation/span-annotation/agent/src/main/resources/META-INF/net.bytebuddy/build.plugins create mode 100644 instrumentation/span-annotation/library/build.gradle.kts create mode 100644 instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt create mode 100644 instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 79d8c8cdf..c93a7b662 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,6 +40,7 @@ okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } opentelemetry-instrumentation-api = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-api" } opentelemetry-instrumentation-apiSemconv = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator", version.ref = "opentelemetry-instrumentation-alpha" } opentelemetry-instrumentation-okhttp = { module = "io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0", version.ref = "opentelemetry-instrumentation-alpha" } +opentelemetry-instrumentation-annotations = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations", version.ref = "opentelemetry-instrumentation-alpha" } opentelemetry-semconv = { module = "io.opentelemetry.semconv:opentelemetry-semconv", version.ref = "opentelemetry-semconv" } opentelemetry-semconv-incubating = { module = "io.opentelemetry.semconv:opentelemetry-semconv-incubating", version.ref = "opentelemetry-semconv-alpha" } opentelemetry-api = { module = "io.opentelemetry:opentelemetry-api" } diff --git a/instrumentation/span-annotation/README.md b/instrumentation/span-annotation/README.md new file mode 100644 index 000000000..b3a425249 --- /dev/null +++ b/instrumentation/span-annotation/README.md @@ -0,0 +1 @@ +placeholder \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/build.gradle.kts b/instrumentation/span-annotation/agent/build.gradle.kts new file mode 100644 index 000000000..31cbb5a28 --- /dev/null +++ b/instrumentation/span-annotation/agent/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("otel.android-library-conventions") + id("otel.publish-conventions") +} + +description = "placeholder" + +android { + namespace = "io.opentelemetry.android.spanannotation.agent" +} + +dependencies { + implementation(libs.opentelemetry.api) + implementation(libs.opentelemetry.context) + implementation(libs.opentelemetry.instrumentation.annotations) + implementation(project(":instrumentation:span-annotation:library")) + implementation(libs.byteBuddy) +} diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt new file mode 100644 index 000000000..38118884c --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt @@ -0,0 +1,116 @@ +package io.opentelemetry.instrumentation.agent.spanannotation + +import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.AddingSpanAttributesConstructorAdvice +import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.SpanAttributeConstructorAdvice +import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.WithSpanConstructorAdvice +import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.AddingSpanAttributesMethodAdvice +import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.SpanAttributeMethodAdvice +import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.WithSpanMethodAdvice +import net.bytebuddy.asm.Advice +import net.bytebuddy.build.Plugin +import net.bytebuddy.description.method.MethodDescription +import net.bytebuddy.description.type.TypeDescription +import net.bytebuddy.dynamic.ClassFileLocator +import net.bytebuddy.dynamic.DynamicType +import net.bytebuddy.matcher.ElementMatchers + +const val WITH_SPAN_ANNOTATION = "io.opentelemetry.instrumentation.annotations.WithSpan" +const val SPAN_ATTRIBUTE_ANNOTATION = "io.opentelemetry.instrumentation.annotations.SpanAttribute" +const val ADDING_SPAN_ATTRIBUTES_ANNOTATION = "io.opentelemetry.instrumentation.annotations.AddingSpanAttributes" + +class SpanAnnotationPlugin : Plugin { + override fun apply( + builder: DynamicType.Builder<*>, + typeDescription: TypeDescription, + classFileLocator: ClassFileLocator + ): DynamicType.Builder<*> { + return builder + // Apply advice to methods annotated with @WithSpan + .visit( + Advice.to(WithSpanMethodAdvice::class.java) + .on( + ElementMatchers.not(ElementMatchers.isConstructor()) + .and(ElementMatchers.isAnnotatedWith( + ElementMatchers.named(WITH_SPAN_ANNOTATION) + ) + ) + ) + ) + // Apply advice to constructors annotated with @WithSpan + .visit( + Advice.to(WithSpanConstructorAdvice::class.java) + .on( + ElementMatchers.isConstructor() + .and(ElementMatchers.isAnnotatedWith( + ElementMatchers.named(WITH_SPAN_ANNOTATION) + ) + ) + ) + ) + // Apply advice to methods annotated with @AddingSpanAttributes + .visit( + Advice.to(AddingSpanAttributesMethodAdvice::class.java) + .on( + ElementMatchers.not(ElementMatchers.isConstructor()) + .and(ElementMatchers.isAnnotatedWith( + ElementMatchers.named(ADDING_SPAN_ATTRIBUTES_ANNOTATION) + ) + ) + ) + ) + // Apply advice to constructors annotated with @AddingSpanAttributes + .visit( + Advice.to(AddingSpanAttributesConstructorAdvice::class.java) + .on( + ElementMatchers.isConstructor() + .and(ElementMatchers.isAnnotatedWith( + ElementMatchers.named(ADDING_SPAN_ATTRIBUTES_ANNOTATION) + ) + ) + ) + ) + // Apply advice to methods with parameters annotated with @SpanAttribute + .visit( + Advice.to(SpanAttributeMethodAdvice::class.java) + .on( + ElementMatchers.not(ElementMatchers.isConstructor()) + .and(ElementMatchers.hasParameters( + ElementMatchers.whereAny( + ElementMatchers.isAnnotatedWith( + ElementMatchers.named(SPAN_ATTRIBUTE_ANNOTATION) + ) + ) + ) + ) + ) + ) + // Apply advice to constructors with parameters annotated with @SpanAttribute + .visit( + Advice.to(SpanAttributeConstructorAdvice::class.java) + .on( + ElementMatchers.isConstructor() + .and(ElementMatchers.hasParameters( + ElementMatchers.whereAny( + ElementMatchers.isAnnotatedWith( + ElementMatchers.named(SPAN_ATTRIBUTE_ANNOTATION) + ) + ) + ) + ) + ) + ) + } + + override fun matches(target: TypeDescription?): Boolean { + return target?.declaredMethods?.any { method -> + method.declaredAnnotations.any { annotation -> + annotation.annotationType.name == WITH_SPAN_ANNOTATION || + annotation.annotationType.name == ADDING_SPAN_ATTRIBUTES_ANNOTATION + } + } == true + } + + override fun close() { + // Nothing here yet? + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt new file mode 100644 index 000000000..cee94f97c --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt @@ -0,0 +1,18 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import net.bytebuddy.asm.Advice +import java.lang.reflect.Constructor + +object AddingSpanAttributesConstructorAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.AllArguments args: Array, + @Advice.Origin constructor: Constructor<*> + ) { + HelperFunctions.argsAsAttributes(Span.current(), args, constructor.declaringClass.simpleName) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt new file mode 100644 index 000000000..85d16ce77 --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt @@ -0,0 +1,23 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import net.bytebuddy.asm.Advice +import java.lang.reflect.Constructor + +object SpanAttributeConstructorAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.AllArguments args: Array, + @Advice.Origin constructor: Constructor<*> + ) { + HelperFunctions.argAsAttribute( + Span.current(), + constructor.parameterAnnotations, + args, + constructor.declaringClass.simpleName + ) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt new file mode 100644 index 000000000..3885bce1e --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt @@ -0,0 +1,30 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.context.Scope +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import io.opentelemetry.instrumentation.annotations.WithSpan +import net.bytebuddy.asm.Advice +import java.lang.reflect.Constructor + +object WithSpanConstructorAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.Origin constructor: Constructor<*> + ) : Pair { + val withSpan = constructor.getAnnotation(WithSpan::class.java) + ?: throw IllegalStateException("WithSpan annotation not found on constructor ${constructor.declaringClass.simpleName}") + + return HelperFunctions.startSpan(withSpan, constructor.declaringClass.simpleName) + } + + @JvmStatic + @Advice.OnMethodExit(suppress = Throwable::class) + fun onExit( + @Advice.Enter spanPair: Pair + ) { + HelperFunctions.stopSpan(spanPair, null) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt new file mode 100644 index 000000000..33216a1cf --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt @@ -0,0 +1,22 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.method + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import net.bytebuddy.asm.Advice +import java.lang.reflect.Method + +object AddingSpanAttributesMethodAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.AllArguments args: Array, + @Advice.Origin method: Method + ) { + HelperFunctions.argsAsAttributes( + Span.current(), + args, + method.name + ) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt new file mode 100644 index 000000000..a103415b8 --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt @@ -0,0 +1,23 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.method + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import net.bytebuddy.asm.Advice +import java.lang.reflect.Method + +object SpanAttributeMethodAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.AllArguments args: Array, + @Advice.Origin method: Method + ) { + HelperFunctions.argAsAttribute( + Span.current(), + method.parameterAnnotations, + args, + method.name + ) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt new file mode 100644 index 000000000..f9864e4b5 --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt @@ -0,0 +1,37 @@ +package io.opentelemetry.instrumentation.agent.spanannotation.advice.method + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.context.Scope +import io.opentelemetry.instrumentation.annotations.WithSpan +import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions +import net.bytebuddy.asm.Advice +import java.lang.reflect.Method + +object WithSpanMethodAdvice { + + @JvmStatic + @Advice.OnMethodEnter(suppress = Throwable::class) + fun onEnter( + @Advice.Origin method: Method + ) : Pair { + val withSpan = method.getAnnotation(WithSpan::class.java) + ?: throw IllegalStateException("WithSpan annotation not found on method ${method.name}") + + return HelperFunctions.startSpan( + withSpan, + method.name + ) + } + + @JvmStatic + @Advice.OnMethodExit(suppress = Throwable::class, onThrowable = Throwable::class) + fun onExit( + @Advice.Enter spanPair: Pair, + @Advice.Thrown throwable: Throwable? + ) { + HelperFunctions.stopSpan( + spanPair, + throwable + ) + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/resources/META-INF/net.bytebuddy/build.plugins b/instrumentation/span-annotation/agent/src/main/resources/META-INF/net.bytebuddy/build.plugins new file mode 100644 index 000000000..0644c3db5 --- /dev/null +++ b/instrumentation/span-annotation/agent/src/main/resources/META-INF/net.bytebuddy/build.plugins @@ -0,0 +1 @@ +io.opentelemetry.instrumentation.agent.spanannotation.SpanAnnotationPlugin \ No newline at end of file diff --git a/instrumentation/span-annotation/library/build.gradle.kts b/instrumentation/span-annotation/library/build.gradle.kts new file mode 100644 index 000000000..358b5fc04 --- /dev/null +++ b/instrumentation/span-annotation/library/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("otel.android-library-conventions") + id("otel.publish-conventions") +} + +description = "placeholder" + +android { + namespace = "io.opentelemetry.android.spanannotation.library" +} + +dependencies { + implementation(libs.opentelemetry.api) + implementation(libs.opentelemetry.context) + implementation(libs.opentelemetry.instrumentation.annotations) + api(project(":instrumentation:android-instrumentation")) +} diff --git a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt new file mode 100644 index 000000000..7e864ac17 --- /dev/null +++ b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt @@ -0,0 +1,59 @@ +package io.opentelemetry.instrumentation.library.spanannotation + +import io.opentelemetry.api.trace.Span +import io.opentelemetry.context.Scope +import io.opentelemetry.instrumentation.annotations.SpanAttribute +import io.opentelemetry.instrumentation.annotations.WithSpan +import kotlin.text.ifEmpty + +object HelperFunctions { + + @JvmStatic + fun startSpan(withSpan: WithSpan, name: String): Pair { + val spanBuilder = SpanAnnotationInstrumentation + .tracer + .spanBuilder(withSpan.value.ifEmpty { name }) + .setSpanKind(withSpan.kind) + + if (!withSpan.inheritContext) { + spanBuilder.setNoParent() + } + + val span = spanBuilder.startSpan() + val scope = span.makeCurrent() + + return Pair(span, scope) + } + + @JvmStatic + fun stopSpan(spanPair: Pair, throwable: Throwable?) { + spanPair.let { (span, scope) -> + throwable?.let { + span.recordException(throwable) + span.setStatus(io.opentelemetry.api.trace.StatusCode.ERROR, it.message ?: "Exception thrown") + } + scope.close() + span.end() + } + } + + @JvmStatic + fun argAsAttribute(span: Span, parameterAnnotations: Array>, args: Array, name: String) { + args.forEachIndexed { index, arg -> + parameterAnnotations[index] + .filterIsInstance() + .firstOrNull()?.let { spanAttribute -> + val attributeKey = spanAttribute.value.takeIf { it.isNotEmpty() } ?: "arg${index}_$name" + span.setAttribute(attributeKey, arg.toString()) + } + } + } + + @JvmStatic + fun argsAsAttributes(span: Span, args: Array, name: String) { + args.forEachIndexed { index, arg -> + val attributeKey = "arg${index}_$name" + span.setAttribute(attributeKey, arg.toString()) + } + } +} \ No newline at end of file diff --git a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt new file mode 100644 index 000000000..8a819ed60 --- /dev/null +++ b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt @@ -0,0 +1,23 @@ +package io.opentelemetry.instrumentation.library.spanannotation + +import com.google.auto.service.AutoService +import io.opentelemetry.android.instrumentation.AndroidInstrumentation +import io.opentelemetry.android.instrumentation.InstallationContext +import io.opentelemetry.api.trace.Tracer + +@AutoService(AndroidInstrumentation::class) +class SpanAnnotationInstrumentation : AndroidInstrumentation { + override val name: String = "span-annotation" + + override fun install(ctx: InstallationContext) { + tracer = + ctx.openTelemetry + .tracerProvider + .tracerBuilder("io.opentelemetry.android.instrumentation.span-annotation") + .build() + } + + companion object { + lateinit var tracer: Tracer + } +} \ No newline at end of file From 25b406a481373df2f99a2f464550527c816167e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kleszcz?= Date: Wed, 5 Nov 2025 13:12:05 +0100 Subject: [PATCH 2/3] Address PR comments and some improvements - Removed constructor implementation for now - Applied @Advice.Origin("#m") in AddingSpanAttributesMethodAdvice.kt - Added basic test for a start - Generated apiDump - Ran spotlessApply - Ran check --- .../span-annotation/agent/api/agent.api | 30 +++++ .../spanannotation/SpanAnnotationPlugin.kt | 121 +++++++----------- .../AddingSpanAttributesMethodAdvice.kt | 12 +- .../method/SpanAttributeMethodAdvice.kt | 12 +- .../advice/method/WithSpanMethodAdvice.kt | 23 ++-- .../span-annotation/library/api/library.api | 21 +++ .../library/spanannotation/HelperFunctions.kt | 43 +++++-- .../SpanAnnotationInstrumentation.kt | 7 +- .../span-annotation/testing/build.gradle.kts | 13 ++ .../spanannotation/InstrumentationTests.kt | 50 ++++++++ .../testing/src/main/AndroidManifest.xml | 2 + .../library/spanannotation/TestApp.kt | 16 +++ 12 files changed, 246 insertions(+), 104 deletions(-) create mode 100644 instrumentation/span-annotation/agent/api/agent.api create mode 100644 instrumentation/span-annotation/library/api/library.api create mode 100644 instrumentation/span-annotation/testing/build.gradle.kts create mode 100644 instrumentation/span-annotation/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/spanannotation/InstrumentationTests.kt create mode 100644 instrumentation/span-annotation/testing/src/main/AndroidManifest.xml create mode 100644 instrumentation/span-annotation/testing/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/TestApp.kt diff --git a/instrumentation/span-annotation/agent/api/agent.api b/instrumentation/span-annotation/agent/api/agent.api new file mode 100644 index 000000000..35225b99f --- /dev/null +++ b/instrumentation/span-annotation/agent/api/agent.api @@ -0,0 +1,30 @@ +public final class io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin : net/bytebuddy/build/Plugin { + public fun ()V + public fun apply (Lnet/bytebuddy/dynamic/DynamicType$Builder;Lnet/bytebuddy/description/type/TypeDescription;Lnet/bytebuddy/dynamic/ClassFileLocator;)Lnet/bytebuddy/dynamic/DynamicType$Builder; + public fun close ()V + public synthetic fun matches (Ljava/lang/Object;)Z + public fun matches (Lnet/bytebuddy/description/type/TypeDescription;)Z +} + +public final class io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPluginKt { + public static final field ADDING_SPAN_ATTRIBUTES_ANNOTATION Ljava/lang/String; + public static final field SPAN_ATTRIBUTE_ANNOTATION Ljava/lang/String; + public static final field WITH_SPAN_ANNOTATION Ljava/lang/String; +} + +public final class io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice { + public static final field INSTANCE Lio/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice; + public static final fun onEnter ([Ljava/lang/Object;Ljava/lang/String;)V +} + +public final class io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice { + public static final field INSTANCE Lio/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice; + public static final fun onEnter ([Ljava/lang/Object;Ljava/lang/reflect/Method;)V +} + +public final class io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice { + public static final field INSTANCE Lio/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice; + public static final fun onEnter (Ljava/lang/reflect/Method;)Lkotlin/Pair; + public static final fun onExit (Lkotlin/Pair;Ljava/lang/Throwable;)V +} + diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt index 38118884c..96eb9fd31 100644 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/SpanAnnotationPlugin.kt @@ -1,14 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.agent.spanannotation -import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.AddingSpanAttributesConstructorAdvice -import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.SpanAttributeConstructorAdvice -import io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor.WithSpanConstructorAdvice import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.AddingSpanAttributesMethodAdvice import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.SpanAttributeMethodAdvice import io.opentelemetry.instrumentation.agent.spanannotation.advice.method.WithSpanMethodAdvice import net.bytebuddy.asm.Advice import net.bytebuddy.build.Plugin -import net.bytebuddy.description.method.MethodDescription import net.bytebuddy.description.type.TypeDescription import net.bytebuddy.dynamic.ClassFileLocator import net.bytebuddy.dynamic.DynamicType @@ -22,95 +23,65 @@ class SpanAnnotationPlugin : Plugin { override fun apply( builder: DynamicType.Builder<*>, typeDescription: TypeDescription, - classFileLocator: ClassFileLocator - ): DynamicType.Builder<*> { - return builder + classFileLocator: ClassFileLocator, + ): DynamicType.Builder<*> = + builder // Apply advice to methods annotated with @WithSpan .visit( - Advice.to(WithSpanMethodAdvice::class.java) - .on( - ElementMatchers.not(ElementMatchers.isConstructor()) - .and(ElementMatchers.isAnnotatedWith( - ElementMatchers.named(WITH_SPAN_ANNOTATION) - ) - ) - ) - ) - // Apply advice to constructors annotated with @WithSpan - .visit( - Advice.to(WithSpanConstructorAdvice::class.java) + Advice + .to(WithSpanMethodAdvice::class.java) .on( - ElementMatchers.isConstructor() - .and(ElementMatchers.isAnnotatedWith( - ElementMatchers.named(WITH_SPAN_ANNOTATION) - ) - ) - ) + ElementMatchers + .not(ElementMatchers.isConstructor()) + .and( + ElementMatchers.isAnnotatedWith( + ElementMatchers.named(WITH_SPAN_ANNOTATION), + ), + ), + ), ) // Apply advice to methods annotated with @AddingSpanAttributes .visit( - Advice.to(AddingSpanAttributesMethodAdvice::class.java) - .on( - ElementMatchers.not(ElementMatchers.isConstructor()) - .and(ElementMatchers.isAnnotatedWith( - ElementMatchers.named(ADDING_SPAN_ATTRIBUTES_ANNOTATION) - ) - ) - ) - ) - // Apply advice to constructors annotated with @AddingSpanAttributes - .visit( - Advice.to(AddingSpanAttributesConstructorAdvice::class.java) + Advice + .to(AddingSpanAttributesMethodAdvice::class.java) .on( - ElementMatchers.isConstructor() - .and(ElementMatchers.isAnnotatedWith( - ElementMatchers.named(ADDING_SPAN_ATTRIBUTES_ANNOTATION) - ) - ) - ) - ) - // Apply advice to methods with parameters annotated with @SpanAttribute - .visit( - Advice.to(SpanAttributeMethodAdvice::class.java) - .on( - ElementMatchers.not(ElementMatchers.isConstructor()) - .and(ElementMatchers.hasParameters( - ElementMatchers.whereAny( + ElementMatchers + .not(ElementMatchers.isConstructor()) + .and( ElementMatchers.isAnnotatedWith( - ElementMatchers.named(SPAN_ATTRIBUTE_ANNOTATION) - ) - ) - ) - ) - ) + ElementMatchers.named(ADDING_SPAN_ATTRIBUTES_ANNOTATION), + ), + ), + ), ) - // Apply advice to constructors with parameters annotated with @SpanAttribute + // Apply advice to methods with parameters annotated with @SpanAttribute .visit( - Advice.to(SpanAttributeConstructorAdvice::class.java) + Advice + .to(SpanAttributeMethodAdvice::class.java) .on( - ElementMatchers.isConstructor() - .and(ElementMatchers.hasParameters( - ElementMatchers.whereAny( - ElementMatchers.isAnnotatedWith( - ElementMatchers.named(SPAN_ATTRIBUTE_ANNOTATION) - ) - ) - ) - ) - ) + ElementMatchers + .not(ElementMatchers.isConstructor()) + .and( + ElementMatchers.hasParameters( + ElementMatchers.whereAny( + ElementMatchers.isAnnotatedWith( + ElementMatchers.named(SPAN_ATTRIBUTE_ANNOTATION), + ), + ), + ), + ), + ), ) - } - override fun matches(target: TypeDescription?): Boolean { - return target?.declaredMethods?.any { method -> + override fun matches(target: TypeDescription?): Boolean = + target?.declaredMethods?.any { method -> method.declaredAnnotations.any { annotation -> annotation.annotationType.name == WITH_SPAN_ANNOTATION || - annotation.annotationType.name == ADDING_SPAN_ATTRIBUTES_ANNOTATION + annotation.annotationType.name == ADDING_SPAN_ATTRIBUTES_ANNOTATION } } == true - } override fun close() { // Nothing here yet? } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt index 33216a1cf..59ddccebd 100644 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/AddingSpanAttributesMethodAdvice.kt @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.agent.spanannotation.advice.method import io.opentelemetry.api.trace.Span @@ -6,17 +11,16 @@ import net.bytebuddy.asm.Advice import java.lang.reflect.Method object AddingSpanAttributesMethodAdvice { - @JvmStatic @Advice.OnMethodEnter(suppress = Throwable::class) fun onEnter( @Advice.AllArguments args: Array, - @Advice.Origin method: Method + @Advice.Origin("#m") methodName: String, ) { HelperFunctions.argsAsAttributes( Span.current(), args, - method.name + methodName, ) } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt index a103415b8..2c8f4dfd0 100644 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/SpanAttributeMethodAdvice.kt @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.agent.spanannotation.advice.method import io.opentelemetry.api.trace.Span @@ -6,18 +11,17 @@ import net.bytebuddy.asm.Advice import java.lang.reflect.Method object SpanAttributeMethodAdvice { - @JvmStatic @Advice.OnMethodEnter(suppress = Throwable::class) fun onEnter( @Advice.AllArguments args: Array, - @Advice.Origin method: Method + @Advice.Origin method: Method, ) { HelperFunctions.argAsAttribute( Span.current(), method.parameterAnnotations, args, - method.name + method.name, ) } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt index f9864e4b5..7df4b9f09 100644 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt +++ b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/method/WithSpanMethodAdvice.kt @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.agent.spanannotation.advice.method import io.opentelemetry.api.trace.Span @@ -8,18 +13,18 @@ import net.bytebuddy.asm.Advice import java.lang.reflect.Method object WithSpanMethodAdvice { - @JvmStatic @Advice.OnMethodEnter(suppress = Throwable::class) fun onEnter( - @Advice.Origin method: Method - ) : Pair { - val withSpan = method.getAnnotation(WithSpan::class.java) - ?: throw IllegalStateException("WithSpan annotation not found on method ${method.name}") + @Advice.Origin method: Method, + ): Pair { + val withSpan = + method.getAnnotation(WithSpan::class.java) + ?: error("WithSpan annotation not found on method ${method.name}") return HelperFunctions.startSpan( withSpan, - method.name + method.name, ) } @@ -27,11 +32,11 @@ object WithSpanMethodAdvice { @Advice.OnMethodExit(suppress = Throwable::class, onThrowable = Throwable::class) fun onExit( @Advice.Enter spanPair: Pair, - @Advice.Thrown throwable: Throwable? + @Advice.Thrown throwable: Throwable?, ) { HelperFunctions.stopSpan( spanPair, - throwable + throwable, ) } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/library/api/library.api b/instrumentation/span-annotation/library/api/library.api new file mode 100644 index 000000000..0663f3bc3 --- /dev/null +++ b/instrumentation/span-annotation/library/api/library.api @@ -0,0 +1,21 @@ +public final class io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions { + public static final field INSTANCE Lio/opentelemetry/instrumentation/library/spanannotation/HelperFunctions; + public static final fun argAsAttribute (Lio/opentelemetry/api/trace/Span;[[Ljava/lang/annotation/Annotation;[Ljava/lang/Object;Ljava/lang/String;)V + public static final fun argsAsAttributes (Lio/opentelemetry/api/trace/Span;[Ljava/lang/Object;Ljava/lang/String;)V + public static final fun startSpan (Lio/opentelemetry/instrumentation/annotations/WithSpan;Ljava/lang/String;)Lkotlin/Pair; + public static final fun stopSpan (Lkotlin/Pair;Ljava/lang/Throwable;)V +} + +public final class io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation : io/opentelemetry/android/instrumentation/AndroidInstrumentation { + public static final field Companion Lio/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation$Companion; + public static field tracer Lio/opentelemetry/api/trace/Tracer; + public fun ()V + public fun getName ()Ljava/lang/String; + public fun install (Lio/opentelemetry/android/instrumentation/InstallationContext;)V +} + +public final class io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation$Companion { + public final fun getTracer ()Lio/opentelemetry/api/trace/Tracer; + public final fun setTracer (Lio/opentelemetry/api/trace/Tracer;)V +} + diff --git a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt index 7e864ac17..1dd0c6d5e 100644 --- a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt +++ b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/HelperFunctions.kt @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.library.spanannotation import io.opentelemetry.api.trace.Span @@ -7,13 +12,16 @@ import io.opentelemetry.instrumentation.annotations.WithSpan import kotlin.text.ifEmpty object HelperFunctions { - @JvmStatic - fun startSpan(withSpan: WithSpan, name: String): Pair { - val spanBuilder = SpanAnnotationInstrumentation - .tracer - .spanBuilder(withSpan.value.ifEmpty { name }) - .setSpanKind(withSpan.kind) + fun startSpan( + withSpan: WithSpan, + name: String, + ): Pair { + val spanBuilder = + SpanAnnotationInstrumentation + .tracer + .spanBuilder(withSpan.value.ifEmpty { name }) + .setSpanKind(withSpan.kind) if (!withSpan.inheritContext) { spanBuilder.setNoParent() @@ -26,7 +34,10 @@ object HelperFunctions { } @JvmStatic - fun stopSpan(spanPair: Pair, throwable: Throwable?) { + fun stopSpan( + spanPair: Pair, + throwable: Throwable?, + ) { spanPair.let { (span, scope) -> throwable?.let { span.recordException(throwable) @@ -38,11 +49,17 @@ object HelperFunctions { } @JvmStatic - fun argAsAttribute(span: Span, parameterAnnotations: Array>, args: Array, name: String) { + fun argAsAttribute( + span: Span, + parameterAnnotations: Array>, + args: Array, + name: String, + ) { args.forEachIndexed { index, arg -> parameterAnnotations[index] .filterIsInstance() - .firstOrNull()?.let { spanAttribute -> + .firstOrNull() + ?.let { spanAttribute -> val attributeKey = spanAttribute.value.takeIf { it.isNotEmpty() } ?: "arg${index}_$name" span.setAttribute(attributeKey, arg.toString()) } @@ -50,10 +67,14 @@ object HelperFunctions { } @JvmStatic - fun argsAsAttributes(span: Span, args: Array, name: String) { + fun argsAsAttributes( + span: Span, + args: Array, + name: String, + ) { args.forEachIndexed { index, arg -> val attributeKey = "arg${index}_$name" span.setAttribute(attributeKey, arg.toString()) } } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt index 8a819ed60..b34f46caa 100644 --- a/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt +++ b/instrumentation/span-annotation/library/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/SpanAnnotationInstrumentation.kt @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.library.spanannotation import com.google.auto.service.AutoService @@ -20,4 +25,4 @@ class SpanAnnotationInstrumentation : AndroidInstrumentation { companion object { lateinit var tracer: Tracer } -} \ No newline at end of file +} diff --git a/instrumentation/span-annotation/testing/build.gradle.kts b/instrumentation/span-annotation/testing/build.gradle.kts new file mode 100644 index 000000000..6df174157 --- /dev/null +++ b/instrumentation/span-annotation/testing/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("otel.android-app-conventions") + id("net.bytebuddy.byte-buddy-gradle-plugin") +} + +android.namespace = "io.opentelemetry.android.spanannotation" + +dependencies { + byteBuddy(project(":instrumentation:span-annotation:agent")) + implementation(project(":instrumentation:span-annotation:library")) + implementation(libs.opentelemetry.instrumentation.annotations) + implementation(project(":test-common")) +} diff --git a/instrumentation/span-annotation/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/spanannotation/InstrumentationTests.kt b/instrumentation/span-annotation/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/spanannotation/InstrumentationTests.kt new file mode 100644 index 000000000..121078161 --- /dev/null +++ b/instrumentation/span-annotation/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/spanannotation/InstrumentationTests.kt @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.library.spanannotation + +import androidx.test.runner.AndroidJUnit4 +import io.opentelemetry.api.common.AttributeKey +import io.opentelemetry.instrumentation.annotations.SpanAttribute +import io.opentelemetry.instrumentation.annotations.WithSpan +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter +import io.opentelemetry.sdk.trace.SdkTracerProvider +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class InstrumentationTests { + private lateinit var spanExporter: InMemorySpanExporter + private lateinit var testApp: TestApp + + @Before + fun setup() { + spanExporter = InMemorySpanExporter.create() + val tracerProvider = + SdkTracerProvider + .builder() + .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) + .build() + + SpanAnnotationInstrumentation.tracer = tracerProvider.get("io.opentelemetry.android.instrumentation.span-annotation") + testApp = TestApp() + } + + @Test + fun testWithSpanAnnotation() { + val result = testApp.annotatedMethod("World") + assertEquals("Hello World", result) + + val exportedSpans = spanExporter.finishedSpanItems + assertEquals(1, exportedSpans.size) + + val span = exportedSpans[0] + assertEquals("Span-Name", span.name) + assertEquals("World", span.attributes.get(AttributeKey.stringKey("attribute"))) + } +} diff --git a/instrumentation/span-annotation/testing/src/main/AndroidManifest.xml b/instrumentation/span-annotation/testing/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8072ee00d --- /dev/null +++ b/instrumentation/span-annotation/testing/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/instrumentation/span-annotation/testing/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/TestApp.kt b/instrumentation/span-annotation/testing/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/TestApp.kt new file mode 100644 index 000000000..754aa4117 --- /dev/null +++ b/instrumentation/span-annotation/testing/src/main/kotlin/io/opentelemetry/instrumentation/library/spanannotation/TestApp.kt @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.library.spanannotation + +import io.opentelemetry.instrumentation.annotations.SpanAttribute +import io.opentelemetry.instrumentation.annotations.WithSpan + +class TestApp { + @WithSpan("Span-Name") + fun annotatedMethod( + @SpanAttribute("attribute") value: String, + ): String = "Hello $value" +} From ed7947d31784a0807972f3fe3690d745f320544d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kleszcz?= Date: Wed, 5 Nov 2025 13:27:38 +0100 Subject: [PATCH 3/3] Remove unused files --- .../AddingSpanAttributesConstructorAdvice.kt | 18 ----------- .../SpanAttributeConstructorAdvice.kt | 23 -------------- .../constructor/WithSpanConstructorAdvice.kt | 30 ------------------- 3 files changed, 71 deletions(-) delete mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt delete mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt delete mode 100644 instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt deleted file mode 100644 index cee94f97c..000000000 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/AddingSpanAttributesConstructorAdvice.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions -import net.bytebuddy.asm.Advice -import java.lang.reflect.Constructor - -object AddingSpanAttributesConstructorAdvice { - - @JvmStatic - @Advice.OnMethodEnter(suppress = Throwable::class) - fun onEnter( - @Advice.AllArguments args: Array, - @Advice.Origin constructor: Constructor<*> - ) { - HelperFunctions.argsAsAttributes(Span.current(), args, constructor.declaringClass.simpleName) - } -} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt deleted file mode 100644 index 85d16ce77..000000000 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/SpanAttributeConstructorAdvice.kt +++ /dev/null @@ -1,23 +0,0 @@ -package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions -import net.bytebuddy.asm.Advice -import java.lang.reflect.Constructor - -object SpanAttributeConstructorAdvice { - - @JvmStatic - @Advice.OnMethodEnter(suppress = Throwable::class) - fun onEnter( - @Advice.AllArguments args: Array, - @Advice.Origin constructor: Constructor<*> - ) { - HelperFunctions.argAsAttribute( - Span.current(), - constructor.parameterAnnotations, - args, - constructor.declaringClass.simpleName - ) - } -} \ No newline at end of file diff --git a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt b/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt deleted file mode 100644 index 3885bce1e..000000000 --- a/instrumentation/span-annotation/agent/src/main/kotlin/io/opentelemetry/instrumentation/agent/spanannotation/advice/constructor/WithSpanConstructorAdvice.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.opentelemetry.instrumentation.agent.spanannotation.advice.constructor - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.context.Scope -import io.opentelemetry.instrumentation.library.spanannotation.HelperFunctions -import io.opentelemetry.instrumentation.annotations.WithSpan -import net.bytebuddy.asm.Advice -import java.lang.reflect.Constructor - -object WithSpanConstructorAdvice { - - @JvmStatic - @Advice.OnMethodEnter(suppress = Throwable::class) - fun onEnter( - @Advice.Origin constructor: Constructor<*> - ) : Pair { - val withSpan = constructor.getAnnotation(WithSpan::class.java) - ?: throw IllegalStateException("WithSpan annotation not found on constructor ${constructor.declaringClass.simpleName}") - - return HelperFunctions.startSpan(withSpan, constructor.declaringClass.simpleName) - } - - @JvmStatic - @Advice.OnMethodExit(suppress = Throwable::class) - fun onExit( - @Advice.Enter spanPair: Pair - ) { - HelperFunctions.stopSpan(spanPair, null) - } -} \ No newline at end of file