From 1cc35c7b7e7acb898dfcba4546fe9387a7425cab Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 6 Dec 2022 13:19:56 +0100 Subject: [PATCH 1/4] Add OpenTelemetryLinkErrorEventProcessor for linking errors to traces created via OpenTelemetry --- ...ryAutoConfigurationCustomizerProvider.java | 1 + .../api/sentry-opentelemetry-core.api | 12 ++--- .../OpenTelemetryLinkErrorEventProcessor.java | 50 +++++++++++++++++++ .../opentelemetry/SentryPropagator.java | 1 + .../opentelemetry/SentrySpanProcessor.java | 1 + sentry/api/sentry.api | 7 +++ .../java/io/sentry}/SentrySpanStorage.java | 3 +- 7 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java rename {sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry => sentry/src/main/java/io/sentry}/SentrySpanStorage.java (94%) diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/src/main/java/io/sentry/opentelemetry/SentryAutoConfigurationCustomizerProvider.java b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/src/main/java/io/sentry/opentelemetry/SentryAutoConfigurationCustomizerProvider.java index b11e988dd32..86c5bab31b9 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/src/main/java/io/sentry/opentelemetry/SentryAutoConfigurationCustomizerProvider.java +++ b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/src/main/java/io/sentry/opentelemetry/SentryAutoConfigurationCustomizerProvider.java @@ -28,6 +28,7 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) { options -> { options.setEnableExternalConfiguration(true); options.setInstrumenter(Instrumenter.OTEL); + options.addEventProcessor(new OpenTelemetryLinkErrorEventProcessor()); final @Nullable SdkVersion sdkVersion = createSdkVersion(options); if (sdkVersion != null) { options.setSdkVersion(sdkVersion); diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api b/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api index 2347a99db77..18c73a9b689 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api +++ b/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api @@ -1,3 +1,8 @@ +public final class io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor : io/sentry/EventProcessor { + public fun ()V + public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent; +} + public final class io/sentry/opentelemetry/OtelSpanInfo { public fun (Ljava/lang/String;Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V public fun getDescription ()Ljava/lang/String; @@ -26,13 +31,6 @@ public final class io/sentry/opentelemetry/SentrySpanProcessor : io/opentelemetr public fun onStart (Lio/opentelemetry/context/Context;Lio/opentelemetry/sdk/trace/ReadWriteSpan;)V } -public final class io/sentry/opentelemetry/SentrySpanStorage { - public fun get (Ljava/lang/String;)Lio/sentry/ISpan; - public static fun getInstance ()Lio/sentry/opentelemetry/SentrySpanStorage; - public fun removeAndGet (Ljava/lang/String;)Lio/sentry/ISpan; - public fun store (Ljava/lang/String;Lio/sentry/ISpan;)V -} - public final class io/sentry/opentelemetry/SpanDescriptionExtractor { public fun ()V public fun extractSpanDescription (Lio/opentelemetry/sdk/trace/ReadableSpan;)Lio/sentry/opentelemetry/OtelSpanInfo; diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java new file mode 100644 index 00000000000..f01d9ec3ed9 --- /dev/null +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java @@ -0,0 +1,50 @@ +package io.sentry.opentelemetry; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanId; +import io.opentelemetry.api.trace.TraceId; +import io.sentry.EventProcessor; +import io.sentry.Hint; +import io.sentry.HubAdapter; +import io.sentry.ISpan; +import io.sentry.Instrumenter; +import io.sentry.SentryEvent; +import io.sentry.SentrySpanStorage; +import io.sentry.SpanContext; +import io.sentry.protocol.SentryId; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class OpenTelemetryLinkErrorEventProcessor implements EventProcessor { + + private final @NotNull SentrySpanStorage spanStorage = SentrySpanStorage.getInstance(); + + @Override + public @Nullable SentryEvent process(final @NotNull SentryEvent event, final @NotNull Hint hint) { + if (Instrumenter.OTEL.equals(HubAdapter.getInstance().getOptions().getInstrumenter())) { + @NotNull final Span otelSpan = Span.current(); + @NotNull final String traceId = otelSpan.getSpanContext().getTraceId(); + @NotNull final String spanId = otelSpan.getSpanContext().getSpanId(); + + if (TraceId.isValid(traceId) && SpanId.isValid(spanId)) { + final @Nullable ISpan sentrySpan = spanStorage.get(spanId); + if (sentrySpan != null) { + final @NotNull SpanContext sentrySpanSpanContext = sentrySpan.getSpanContext(); + final @NotNull String operation = sentrySpanSpanContext.getOperation(); + final @Nullable io.sentry.SpanId parentSpanId = sentrySpanSpanContext.getParentSpanId(); + final @NotNull SpanContext spanContext = + new SpanContext( + new SentryId(traceId), + new io.sentry.SpanId(spanId), + operation, + parentSpanId, + null); + + event.getContexts().setTrace(spanContext); + } + } + } + + return event; + } +} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java index 85ba4b3b304..f82f747c85b 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java @@ -11,6 +11,7 @@ import io.sentry.Baggage; import io.sentry.BaggageHeader; import io.sentry.ISpan; +import io.sentry.SentrySpanStorage; import io.sentry.SentryTraceHeader; import io.sentry.exception.InvalidSentryTraceHeaderException; import java.util.Arrays; diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java index 0daa6cab649..fba597a48c8 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java @@ -19,6 +19,7 @@ import io.sentry.ISpan; import io.sentry.ITransaction; import io.sentry.Instrumenter; +import io.sentry.SentrySpanStorage; import io.sentry.SentryTraceHeader; import io.sentry.SpanId; import io.sentry.SpanStatus; diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 6993f1f6b2a..85f6c240224 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -1562,6 +1562,13 @@ public abstract interface class io/sentry/SentryOptions$TracesSamplerCallback { public abstract fun sample (Lio/sentry/SamplingContext;)Ljava/lang/Double; } +public final class io/sentry/SentrySpanStorage { + public fun get (Ljava/lang/String;)Lio/sentry/ISpan; + public static fun getInstance ()Lio/sentry/SentrySpanStorage; + public fun removeAndGet (Ljava/lang/String;)Lio/sentry/ISpan; + public fun store (Ljava/lang/String;Lio/sentry/ISpan;)V +} + public final class io/sentry/SentryTraceHeader { public static final field SENTRY_TRACE_HEADER Ljava/lang/String; public fun (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/Boolean;)V diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanStorage.java b/sentry/src/main/java/io/sentry/SentrySpanStorage.java similarity index 94% rename from sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanStorage.java rename to sentry/src/main/java/io/sentry/SentrySpanStorage.java index 9898fc5c4c0..8b9e27497e8 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanStorage.java +++ b/sentry/src/main/java/io/sentry/SentrySpanStorage.java @@ -1,6 +1,5 @@ -package io.sentry.opentelemetry; +package io.sentry; -import io.sentry.ISpan; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.jetbrains.annotations.ApiStatus; From bc2ec93b16bed32524634f678022ace0fe3feeb4 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 6 Dec 2022 13:34:41 +0100 Subject: [PATCH 2/4] Add changelog --- CHANGELOG.md | 1 + sentry/src/main/java/io/sentry/SentrySpanStorage.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85dad51cd5..ff00a15eada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Features - Add SENTRY_AUTO_INIT environment variable to control OpenTelemetry Agent init ([#2410](https://github.com/getsentry/sentry-java/pull/2410)) +- Add OpenTelemetryLinkErrorEventProcessor for linking errors to traces created via OpenTelemetry ([#2418](https://github.com/getsentry/sentry-java/pull/2418)) ## 6.9.1 diff --git a/sentry/src/main/java/io/sentry/SentrySpanStorage.java b/sentry/src/main/java/io/sentry/SentrySpanStorage.java index 8b9e27497e8..b260f06e5c0 100644 --- a/sentry/src/main/java/io/sentry/SentrySpanStorage.java +++ b/sentry/src/main/java/io/sentry/SentrySpanStorage.java @@ -6,6 +6,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * Has been moved to `sentry` gradle module to include it in the bootstrap classloader without + * having to introduce yet another module for OpenTelemetry support. + */ @ApiStatus.Internal public final class SentrySpanStorage { private static volatile @Nullable SentrySpanStorage INSTANCE; From 2702690e2ac93bfd46b2b4da2a49874be9fb8719 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 6 Dec 2022 15:53:23 +0100 Subject: [PATCH 3/4] Bump OTEL to 1.20; reuse dependency configs --- buildSrc/src/main/java/Config.kt | 17 +++++++++++++---- .../sentry-opentelemetry-agent/build.gradle.kts | 16 ++++++++++------ .../build.gradle.kts | 8 ++++---- .../sentry-opentelemetry-core/build.gradle.kts | 8 ++++---- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 11c226acdcc..6afbb8095b6 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -132,10 +132,19 @@ object Config { val apolloKotlin = "com.apollographql.apollo3:apollo-runtime:3.3.0" - val otelVersion = "1.19.0" - val otelAlphaVersion = "1.19.0-alpha" - val otelJavaagentVersion = "1.19.2" - val otelJavaagentAlphaVersion = "1.19.2-alpha" + object OpenTelemetry { + val otelVersion = "1.20.1" + val otelAlphaVersion = "1.20.1-alpha" + val otelJavaagentVersion = "1.20.2" + val otelJavaagentAlphaVersion = "1.20.2-alpha" + + val otelSdk = "io.opentelemetry:opentelemetry-sdk:$otelVersion" + val otelSemconv = "io.opentelemetry:opentelemetry-semconv:$otelAlphaVersion" + val otelJavaAgent = "io.opentelemetry.javaagent:opentelemetry-javaagent:$otelJavaagentVersion" + val otelJavaAgentExtensionApi = "io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api:$otelJavaagentAlphaVersion" + val otelJavaAgentTooling = "io.opentelemetry.javaagent:opentelemetry-javaagent-tooling:$otelJavaagentAlphaVersion" + val otelExtensionAutoconfigureSpi = "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:$otelVersion" + } } object AnnotationProcessors { diff --git a/sentry-opentelemetry/sentry-opentelemetry-agent/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-agent/build.gradle.kts index 495e200f248..80b68430db2 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agent/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-agent/build.gradle.kts @@ -14,8 +14,12 @@ fun relocatePackages(shadowJar: ShadowJar) { // rewrite dependencies calling Logger.getLogger shadowJar.relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger") - // rewrite library instrumentation dependencies - shadowJar.relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation") + // prevents conflict with library instrumentation, since these classes live in the bootstrap class loader + shadowJar.relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation") { + // Exclude resource providers since they live in the agent class loader + exclude("io.opentelemetry.instrumentation.resources.*") + exclude("io.opentelemetry.instrumentation.spring.resources.*") + } // relocate OpenTelemetry API usage shadowJar.relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") @@ -50,7 +54,7 @@ val upstreamAgent = configurations.create("upstreamAgent") { dependencies { bootstrapLibs(projects.sentry) javaagentLibs(projects.sentryOpentelemetry.sentryOpentelemetryAgentcustomization) - upstreamAgent("io.opentelemetry.javaagent:opentelemetry-javaagent:${Config.Libs.otelJavaagentVersion}") + upstreamAgent(Config.Libs.OpenTelemetry.otelJavaAgent) } fun isolateClasses(jars: Iterable): CopySpec { @@ -146,11 +150,11 @@ tasks { attributes.put("Can-Redefine-Classes", "true") attributes.put("Can-Retransform-Classes", "true") attributes.put("Implementation-Vendor", "Sentry") - attributes.put("Implementation-Version", "sentry-${project.version}-otel-${Config.Libs.otelJavaagentVersion}") + attributes.put("Implementation-Version", "sentry-${project.version}-otel-${Config.Libs.OpenTelemetry.otelJavaagentVersion}") attributes.put("Sentry-Version-Name", project.version) attributes.put("Sentry-Opentelemetry-SDK-Name", Config.Sentry.SENTRY_OPENTELEMETRY_AGENT_SDK_NAME) - attributes.put("Sentry-Opentelemetry-Version-Name", Config.Libs.otelVersion) - attributes.put("Sentry-Opentelemetry-Javaagent-Version-Name", Config.Libs.otelJavaagentVersion) + attributes.put("Sentry-Opentelemetry-Version-Name", Config.Libs.OpenTelemetry.otelVersion) + attributes.put("Sentry-Opentelemetry-Javaagent-Version-Name", Config.Libs.OpenTelemetry.otelJavaagentVersion) } } diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts index 0b0dc08ca1e..a9b7f3666fb 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts @@ -22,10 +22,10 @@ dependencies { compileOnly(projects.sentry) implementation(projects.sentryOpentelemetry.sentryOpentelemetryCore) - compileOnly("io.opentelemetry:opentelemetry-sdk:${Config.Libs.otelVersion}") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:${Config.Libs.otelVersion}") - compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api:${Config.Libs.otelJavaagentAlphaVersion}") - compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling:${Config.Libs.otelJavaagentAlphaVersion}") + compileOnly(Config.Libs.OpenTelemetry.otelSdk) + compileOnly(Config.Libs.OpenTelemetry.otelExtensionAutoconfigureSpi) + compileOnly(Config.Libs.OpenTelemetry.otelJavaAgentExtensionApi) + compileOnly(Config.Libs.OpenTelemetry.otelJavaAgentTooling) compileOnly(Config.CompileOnly.nopen) errorprone(Config.CompileOnly.nopenChecker) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts index c9c248ee01e..c8db1650b28 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts @@ -21,8 +21,8 @@ tasks.withType().configureEach { dependencies { compileOnly(projects.sentry) - compileOnly("io.opentelemetry:opentelemetry-sdk:${Config.Libs.otelVersion}") - compileOnly("io.opentelemetry:opentelemetry-semconv:${Config.Libs.otelAlphaVersion}") + compileOnly(Config.Libs.OpenTelemetry.otelSdk) + compileOnly(Config.Libs.OpenTelemetry.otelSemconv) compileOnly(Config.CompileOnly.nopen) errorprone(Config.CompileOnly.nopenChecker) @@ -37,8 +37,8 @@ dependencies { testImplementation(Config.TestLibs.mockitoKotlin) testImplementation(Config.TestLibs.awaitility) - testImplementation("io.opentelemetry:opentelemetry-sdk:${Config.Libs.otelVersion}") - testImplementation("io.opentelemetry:opentelemetry-semconv:${Config.Libs.otelAlphaVersion}") + testImplementation(Config.Libs.OpenTelemetry.otelSdk) + testImplementation(Config.Libs.OpenTelemetry.otelSemconv) } configure { From 4e3bb5e98f02fd676e95098417ccdb09d8e8bed5 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Tue, 6 Dec 2022 15:59:57 +0100 Subject: [PATCH 4/4] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b609c4ef0fe..d2fffce60df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ - Add SENTRY_AUTO_INIT environment variable to control OpenTelemetry Agent init ([#2410](https://github.com/getsentry/sentry-java/pull/2410)) - Add OpenTelemetryLinkErrorEventProcessor for linking errors to traces created via OpenTelemetry ([#2418](https://github.com/getsentry/sentry-java/pull/2418)) +### Dependencies + +- Bump OpenTelemetry to 1.20.1 and OpenTelemetry Java Agent to 1.20.2 ([#2420](https://github.com/getsentry/sentry-java/pull/2420)) + ## 6.9.1 ### Fixes