From d2b5881176fb6e77e8065cc9beaa62273f509ca9 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 4 Jul 2024 13:11:07 +0200 Subject: [PATCH 1/7] Use parent span id from sentry-trace header --- .../sentry/opentelemetry/OtelSentrySpanProcessor.java | 11 +++++++++-- .../java/io/sentry/opentelemetry/SentrySampler.java | 1 + .../api/sentry-opentelemetry-extra.api | 4 ++-- .../java/io/sentry/opentelemetry/OtelSpanContext.java | 3 ++- .../java/io/sentry/opentelemetry/OtelSpanWrapper.java | 4 +++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentrySpanProcessor.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentrySpanProcessor.java index 8dd4bd160aa..74399068681 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentrySpanProcessor.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentrySpanProcessor.java @@ -53,13 +53,14 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri TracesSamplingDecision samplingDecision = OtelSamplingUtil.extractSamplingDecisionOrDefault(otelSpan.toSpanData().getAttributes()); @Nullable Baggage baggage = null; + @Nullable SpanId sentryParentSpanId = null; otelSpan.setAttribute(IS_REMOTE_PARENT, otelSpan.getParentSpanContext().isRemote()); if (sentryParentSpan == null) { final @NotNull String traceId = otelSpan.getSpanContext().getTraceId(); final @NotNull String spanId = otelSpan.getSpanContext().getSpanId(); final @NotNull SpanId sentrySpanId = new SpanId(spanId); final @NotNull String parentSpanId = otelSpan.getParentSpanContext().getSpanId(); - final @Nullable SpanId sentryParentSpanId = + sentryParentSpanId = io.opentelemetry.api.trace.SpanId.isValid(parentSpanId) ? new SpanId(parentSpanId) : null; @Nullable @@ -99,7 +100,13 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri new SentryLongDate(otelSpan.toSpanData().getStartEpochNanos()); final @NotNull OtelSpanWrapper sentrySpan = new OtelSpanWrapper( - otelSpan, scopes, startTimestamp, samplingDecision, sentryParentSpan, baggage); + otelSpan, + scopes, + startTimestamp, + samplingDecision, + sentryParentSpan, + sentryParentSpanId, + baggage); sentrySpan.getSpanContext().setOrigin(SentrySpanExporter.TRACE_ORIGIN); spanStorage.storeSentrySpan(spanContext, sentrySpan); } diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java index 37df216ebb5..6412badc262 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java @@ -94,6 +94,7 @@ public SamplingResult shouldSample( .getOptions() .getInternalTracesSampler() .sample(new SamplingContext(transactionContext, null)); + // TODO [POTEL] if sampling decision = false, we should record it in client report return new SentrySamplingResult(sentryDecision); } diff --git a/sentry-opentelemetry/sentry-opentelemetry-extra/api/sentry-opentelemetry-extra.api b/sentry-opentelemetry/sentry-opentelemetry-extra/api/sentry-opentelemetry-extra.api index 83ca7461f6b..498ec31c4e6 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-extra/api/sentry-opentelemetry-extra.api +++ b/sentry-opentelemetry/sentry-opentelemetry-extra/api/sentry-opentelemetry-extra.api @@ -11,7 +11,7 @@ public final class io/sentry/opentelemetry/OtelContextScopesStorage : io/sentry/ } public final class io/sentry/opentelemetry/OtelSpanContext : io/sentry/SpanContext { - public fun (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;Lio/sentry/Baggage;)V + public fun (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;Lio/sentry/SpanId;Lio/sentry/Baggage;)V public fun getOperation ()Ljava/lang/String; public fun getStatus ()Lio/sentry/SpanStatus; public fun setOperation (Ljava/lang/String;)V @@ -27,7 +27,7 @@ public final class io/sentry/opentelemetry/OtelSpanFactory : io/sentry/ISpanFact } public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/ISpan { - public fun (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/IScopes;Lio/sentry/SentryDate;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;Lio/sentry/Baggage;)V + public fun (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/IScopes;Lio/sentry/SentryDate;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;Lio/sentry/SpanId;Lio/sentry/Baggage;)V public fun finish ()V public fun finish (Lio/sentry/SpanStatus;)V public fun finish (Lio/sentry/SpanStatus;Lio/sentry/SentryDate;)V diff --git a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanContext.java b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanContext.java index 7b279802c94..626b837c97f 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanContext.java +++ b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanContext.java @@ -30,11 +30,12 @@ public OtelSpanContext( final @NotNull ReadWriteSpan span, final @Nullable TracesSamplingDecision samplingDecision, final @Nullable OtelSpanWrapper parentSpan, + final @Nullable SpanId parentSpanId, final @Nullable Baggage baggage) { super( new SentryId(span.getSpanContext().getTraceId()), new SpanId(span.getSpanContext().getSpanId()), - parentSpan == null ? null : parentSpan.getSpanContext().getSpanId(), + parentSpan == null ? parentSpanId : parentSpan.getSpanContext().getSpanId(), span.getName(), null, samplingDecision != null diff --git a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanWrapper.java b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanWrapper.java index 9ab01d60bdb..a21c8310732 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanWrapper.java +++ b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/OtelSpanWrapper.java @@ -88,6 +88,7 @@ public OtelSpanWrapper( final @NotNull SentryDate startTimestamp, final @Nullable TracesSamplingDecision samplingDecision, final @Nullable OtelSpanWrapper parentSpan, + final @Nullable SpanId parentSpanId, final @Nullable Baggage baggage) { this.scopes = Objects.requireNonNull(scopes, "scopes are required"); this.span = new WeakReference<>(span); @@ -101,7 +102,8 @@ public OtelSpanWrapper( this.baggage = null; } - this.context = new OtelSpanContext(span, samplingDecision, parentSpan, this.baggage); + this.context = + new OtelSpanContext(span, samplingDecision, parentSpan, parentSpanId, this.baggage); } @Override From 8cf3731994e47eae63e4b41d9cf543dc973274d3 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 4 Jul 2024 16:04:39 +0200 Subject: [PATCH 2/7] attach active span to scope --- .../opentelemetry/SentryContextWrapper.java | 29 +++++++++++-------- sentry/api/sentry.api | 11 +++++++ .../java/io/sentry/CombinedScopeView.java | 5 ++++ .../src/main/java/io/sentry/HubAdapter.java | 5 ++++ .../main/java/io/sentry/HubScopesWrapper.java | 5 ++++ sentry/src/main/java/io/sentry/IScope.java | 3 ++ sentry/src/main/java/io/sentry/IScopes.java | 3 ++ sentry/src/main/java/io/sentry/NoOpHub.java | 3 ++ sentry/src/main/java/io/sentry/NoOpScope.java | 3 ++ .../src/main/java/io/sentry/NoOpScopes.java | 3 ++ sentry/src/main/java/io/sentry/Scope.java | 12 ++++++++ sentry/src/main/java/io/sentry/Scopes.java | 5 ++++ .../main/java/io/sentry/ScopesAdapter.java | 5 ++++ 13 files changed, 80 insertions(+), 12 deletions(-) diff --git a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/SentryContextWrapper.java b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/SentryContextWrapper.java index e2a5efaf89c..20600fb243f 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/SentryContextWrapper.java +++ b/sentry-opentelemetry/sentry-opentelemetry-extra/src/main/java/io/sentry/opentelemetry/SentryContextWrapper.java @@ -41,39 +41,44 @@ private boolean isOpentelemetrySpan(final @NotNull ContextKey contextKey) } private static @NotNull Context forkCurrentScope(final @NotNull Context context) { + final @Nullable OtelSpanWrapper sentrySpan = getCurrentSpanFromGlobalStorage(context); + final @Nullable IScopes spanScopes = sentrySpan == null ? null : sentrySpan.getScopes(); + final @NotNull IScopes forkedScopes = forkCurrentScopeInternal(context, spanScopes); + if (sentrySpan != null) { + forkedScopes.setActiveSpan(sentrySpan); + } + return context.with(SENTRY_SCOPES_KEY, forkedScopes); + } + + private static @NotNull IScopes forkCurrentScopeInternal( + final @NotNull Context context, final @Nullable IScopes spanScopes) { final @Nullable IScopes scopesInContext = context.get(SENTRY_SCOPES_KEY); - final @Nullable IScopes spanScopes = getCurrentSpanScopesFromGlobalStorage(context); if (scopesInContext != null && spanScopes != null) { if (scopesInContext.isAncestorOf(spanScopes)) { - return context.with( - SENTRY_SCOPES_KEY, spanScopes.forkedCurrentScope("contextwrapper.spanancestor")); + return spanScopes.forkedCurrentScope("contextwrapper.spanancestor"); } } if (scopesInContext != null) { - return context.with( - SENTRY_SCOPES_KEY, scopesInContext.forkedCurrentScope("contextwrapper.scopeincontext")); + return scopesInContext.forkedCurrentScope("contextwrapper.scopeincontext"); } if (spanScopes != null) { - return context.with( - SENTRY_SCOPES_KEY, spanScopes.forkedCurrentScope("contextwrapper.spanscope")); + return spanScopes.forkedCurrentScope("contextwrapper.spanscope"); } - return context.with(SENTRY_SCOPES_KEY, Sentry.forkedRootScopes("contextwrapper.fallback")); + return Sentry.forkedRootScopes("contextwrapper.fallback"); } - private static @Nullable IScopes getCurrentSpanScopesFromGlobalStorage( + private static @Nullable OtelSpanWrapper getCurrentSpanFromGlobalStorage( final @NotNull Context context) { @Nullable final Span span = Span.fromContextOrNull(context); if (span != null) { final @Nullable OtelSpanWrapper sentrySpan = SentryWeakSpanStorage.getInstance().getSentrySpan(span.getSpanContext()); - if (sentrySpan != null) { - return sentrySpan.getScopes(); - } + return sentrySpan; } return null; diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 52d6c2f3295..0ec7a37cdc0 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -279,6 +279,7 @@ public final class io/sentry/CombinedScopeView : io/sentry/IScope { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun replaceOptions (Lio/sentry/SentryOptions;)V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Boolean;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Character;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Number;)V @@ -580,6 +581,7 @@ public final class io/sentry/HubAdapter : io/sentry/IHub { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V @@ -644,6 +646,7 @@ public final class io/sentry/HubScopesWrapper : io/sentry/IHub { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V @@ -770,6 +773,7 @@ public abstract interface class io/sentry/IScope { public abstract fun removeExtra (Ljava/lang/String;)V public abstract fun removeTag (Ljava/lang/String;)V public abstract fun replaceOptions (Lio/sentry/SentryOptions;)V + public abstract fun setActiveSpan (Lio/sentry/ISpan;)V public abstract fun setContexts (Ljava/lang/String;Ljava/lang/Boolean;)V public abstract fun setContexts (Ljava/lang/String;Ljava/lang/Character;)V public abstract fun setContexts (Ljava/lang/String;Ljava/lang/Number;)V @@ -876,6 +880,7 @@ public abstract interface class io/sentry/IScopes { public abstract fun removeTag (Ljava/lang/String;)V public fun reportFullDisplayed ()V public abstract fun reportFullyDisplayed ()V + public abstract fun setActiveSpan (Lio/sentry/ISpan;)V public abstract fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public abstract fun setFingerprint (Ljava/util/List;)V public abstract fun setLevel (Lio/sentry/SentryLevel;)V @@ -1385,6 +1390,7 @@ public final class io/sentry/NoOpHub : io/sentry/IHub { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V @@ -1447,6 +1453,7 @@ public final class io/sentry/NoOpScope : io/sentry/IScope { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun replaceOptions (Lio/sentry/SentryOptions;)V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Boolean;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Character;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Number;)V @@ -1523,6 +1530,7 @@ public final class io/sentry/NoOpScopes : io/sentry/IScopes { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V @@ -1919,6 +1927,7 @@ public final class io/sentry/Scope : io/sentry/IScope { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun replaceOptions (Lio/sentry/SentryOptions;)V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Boolean;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Character;)V public fun setContexts (Ljava/lang/String;Ljava/lang/Number;)V @@ -2038,6 +2047,7 @@ public final class io/sentry/Scopes : io/sentry/IScopes, io/sentry/metrics/Metri public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V @@ -2103,6 +2113,7 @@ public final class io/sentry/ScopesAdapter : io/sentry/IScopes { public fun removeExtra (Ljava/lang/String;)V public fun removeTag (Ljava/lang/String;)V public fun reportFullyDisplayed ()V + public fun setActiveSpan (Lio/sentry/ISpan;)V public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V public fun setFingerprint (Ljava/util/List;)V public fun setLevel (Lio/sentry/SentryLevel;)V diff --git a/sentry/src/main/java/io/sentry/CombinedScopeView.java b/sentry/src/main/java/io/sentry/CombinedScopeView.java index c22fd060bb3..a4143fe2e62 100644 --- a/sentry/src/main/java/io/sentry/CombinedScopeView.java +++ b/sentry/src/main/java/io/sentry/CombinedScopeView.java @@ -84,6 +84,11 @@ public void setTransaction(@NotNull String transaction) { return globalScope.getSpan(); } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + scope.setActiveSpan(span); + } + @Override public void setTransaction(@Nullable ITransaction transaction) { getDefaultWriteScope().setTransaction(transaction); diff --git a/sentry/src/main/java/io/sentry/HubAdapter.java b/sentry/src/main/java/io/sentry/HubAdapter.java index 8ba2ae91938..48ddeb67db8 100644 --- a/sentry/src/main/java/io/sentry/HubAdapter.java +++ b/sentry/src/main/java/io/sentry/HubAdapter.java @@ -297,6 +297,11 @@ public void setSpanContext( return Sentry.getCurrentScopes().getSpan(); } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + Sentry.getCurrentScopes().setActiveSpan(span); + } + @Override @ApiStatus.Internal public @Nullable ITransaction getTransaction() { diff --git a/sentry/src/main/java/io/sentry/HubScopesWrapper.java b/sentry/src/main/java/io/sentry/HubScopesWrapper.java index 371321eaf29..341ec121d94 100644 --- a/sentry/src/main/java/io/sentry/HubScopesWrapper.java +++ b/sentry/src/main/java/io/sentry/HubScopesWrapper.java @@ -290,6 +290,11 @@ public void setSpanContext( return scopes.getSpan(); } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + scopes.setActiveSpan(span); + } + @ApiStatus.Internal @Override public @Nullable ITransaction getTransaction() { diff --git a/sentry/src/main/java/io/sentry/IScope.java b/sentry/src/main/java/io/sentry/IScope.java index 6d6ddfb4ce2..4bafec185e0 100644 --- a/sentry/src/main/java/io/sentry/IScope.java +++ b/sentry/src/main/java/io/sentry/IScope.java @@ -47,6 +47,9 @@ public interface IScope { @Nullable ISpan getSpan(); + @ApiStatus.Internal + void setActiveSpan(@Nullable ISpan span); + /** * Sets the current active transaction * diff --git a/sentry/src/main/java/io/sentry/IScopes.java b/sentry/src/main/java/io/sentry/IScopes.java index 400f08e4576..1c9a06c9093 100644 --- a/sentry/src/main/java/io/sentry/IScopes.java +++ b/sentry/src/main/java/io/sentry/IScopes.java @@ -614,6 +614,9 @@ void setSpanContext( @Nullable ISpan getSpan(); + @ApiStatus.Internal + void setActiveSpan(@Nullable ISpan span); + /** * Returns the transaction. * diff --git a/sentry/src/main/java/io/sentry/NoOpHub.java b/sentry/src/main/java/io/sentry/NoOpHub.java index 55893746d88..a0e6a44acd3 100644 --- a/sentry/src/main/java/io/sentry/NoOpHub.java +++ b/sentry/src/main/java/io/sentry/NoOpHub.java @@ -260,6 +260,9 @@ public void setSpanContext( return null; } + @Override + public void setActiveSpan(final @Nullable ISpan span) {} + @Override public @Nullable ITransaction getTransaction() { return null; diff --git a/sentry/src/main/java/io/sentry/NoOpScope.java b/sentry/src/main/java/io/sentry/NoOpScope.java index fd258fd7c67..af94bd6a8c7 100644 --- a/sentry/src/main/java/io/sentry/NoOpScope.java +++ b/sentry/src/main/java/io/sentry/NoOpScope.java @@ -49,6 +49,9 @@ public void setTransaction(@NotNull String transaction) {} return null; } + @Override + public void setActiveSpan(final @Nullable ISpan span) {} + @Override public void setTransaction(@Nullable ITransaction transaction) {} diff --git a/sentry/src/main/java/io/sentry/NoOpScopes.java b/sentry/src/main/java/io/sentry/NoOpScopes.java index 58c1207809b..e27c8f294a8 100644 --- a/sentry/src/main/java/io/sentry/NoOpScopes.java +++ b/sentry/src/main/java/io/sentry/NoOpScopes.java @@ -255,6 +255,9 @@ public void setSpanContext( return null; } + @Override + public void setActiveSpan(final @Nullable ISpan span) {} + @Override public @Nullable ITransaction getTransaction() { return null; diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 8b47bddf38d..f8c431c1917 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -38,6 +38,8 @@ public final class Scope implements IScope { /** Scope's {@link ITransaction}. */ private @Nullable ITransaction transaction; + private @NotNull WeakReference activeSpan = new WeakReference<>(null); + /** Scope's transaction name. Used when using error reporting without the performance feature. */ private @Nullable String transactionName; @@ -232,6 +234,11 @@ public void setTransaction(final @NotNull String transaction) { @Nullable @Override public ISpan getSpan() { + final @Nullable ISpan activeSpan = this.activeSpan.get(); + if (activeSpan != null) { + return activeSpan; + } + final ITransaction tx = transaction; if (tx != null) { final ISpan span = tx.getLatestActiveSpan(); @@ -243,6 +250,11 @@ public ISpan getSpan() { return tx; } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + activeSpan = new WeakReference<>(span); + } + /** * Sets the current active transaction * diff --git a/sentry/src/main/java/io/sentry/Scopes.java b/sentry/src/main/java/io/sentry/Scopes.java index 1e26eefeba3..6ed1fa2b345 100644 --- a/sentry/src/main/java/io/sentry/Scopes.java +++ b/sentry/src/main/java/io/sentry/Scopes.java @@ -933,6 +933,11 @@ public void setSpanContext( return null; } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + getCombinedScopeView().setActiveSpan(span); + } + @Override @ApiStatus.Internal public @Nullable ITransaction getTransaction() { diff --git a/sentry/src/main/java/io/sentry/ScopesAdapter.java b/sentry/src/main/java/io/sentry/ScopesAdapter.java index 92387dc6025..be10b1fe039 100644 --- a/sentry/src/main/java/io/sentry/ScopesAdapter.java +++ b/sentry/src/main/java/io/sentry/ScopesAdapter.java @@ -297,6 +297,11 @@ public void setSpanContext( return Sentry.getCurrentScopes().getSpan(); } + @Override + public void setActiveSpan(final @Nullable ISpan span) { + Sentry.getCurrentScopes().setActiveSpan(span); + } + @Override @ApiStatus.Internal public @Nullable ITransaction getTransaction() { From 48fc6f850b11ee8becbe1ffba1a22acf46df758d Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 5 Jul 2024 11:20:04 +0200 Subject: [PATCH 3/7] record dropped span/transaction in SentrySampler --- .../io/sentry/opentelemetry/SentrySampler.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java index 6412badc262..60a9ae11ecb 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java @@ -11,6 +11,7 @@ import io.opentelemetry.sdk.trace.samplers.SamplingDecision; import io.opentelemetry.sdk.trace.samplers.SamplingResult; import io.sentry.Baggage; +import io.sentry.DataCategory; import io.sentry.IScopes; import io.sentry.PropagationContext; import io.sentry.SamplingContext; @@ -19,6 +20,7 @@ import io.sentry.SpanId; import io.sentry.TracesSamplingDecision; import io.sentry.TransactionContext; +import io.sentry.clientreport.DiscardReason; import io.sentry.protocol.SentryId; import java.util.List; import org.jetbrains.annotations.NotNull; @@ -94,7 +96,18 @@ public SamplingResult shouldSample( .getOptions() .getInternalTracesSampler() .sample(new SamplingContext(transactionContext, null)); - // TODO [POTEL] if sampling decision = false, we should record it in client report + + if (!sentryDecision.getSampled()) { + scopes + .getOptions() + .getClientReportRecorder() + .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Transaction); + scopes + .getOptions() + .getClientReportRecorder() + .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Span); + } + return new SentrySamplingResult(sentryDecision); } From 286fb013e8b970bee70f7820d29711f69e2688b5 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 5 Jul 2024 15:27:11 +0200 Subject: [PATCH 4/7] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c66d53b950..b427a01c9c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Traces were broken because on an incoming request, OtelSentrySpanProcessor did not set the parentSpanId on the span correctly. Traces were not referencing the actual parent span but some other (random) span ID which the server doesn't know. - Attach active span to scope when using OpenTelemetry ([#3549](https://github.com/getsentry/sentry-java/pull/3549)) - Errors weren't linked to traces correctly due to parts of the SDK not knowing the current span +- Record dropped spans in client report when sampling out OpenTelemetry spans ([#3552](https://github.com/getsentry/sentry-java/pull/3552)) ## 8.0.0-alpha.3 From 9206bc660cdd9553717329cc5bfbe04e5d329caa Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 5 Jul 2024 15:55:14 +0200 Subject: [PATCH 5/7] record lost span when copying parent decision --- .../main/java/io/sentry/opentelemetry/SentrySampler.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java index 60a9ae11ecb..3c5ee1fd729 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java @@ -116,6 +116,12 @@ public SamplingResult shouldSample( final @Nullable TracesSamplingDecision parentSamplingDecision = parentSentrySpan.getSamplingDecision(); if (parentSamplingDecision != null) { + if (!parentSentrySpan.isSampled()) { + scopes + .getOptions() + .getClientReportRecorder() + .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Span); + } return new SentrySamplingResult(parentSamplingDecision); } else { // this should never happen and only serve to calm the compiler From 40dab84116b6714d557de2d08f3b92caffd0e275 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Fri, 5 Jul 2024 13:57:41 +0000 Subject: [PATCH 6/7] Format code --- .../main/java/io/sentry/opentelemetry/SentrySampler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java index 3c5ee1fd729..b170fdb8a56 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java @@ -118,9 +118,9 @@ public SamplingResult shouldSample( if (parentSamplingDecision != null) { if (!parentSentrySpan.isSampled()) { scopes - .getOptions() - .getClientReportRecorder() - .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Span); + .getOptions() + .getClientReportRecorder() + .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Span); } return new SentrySamplingResult(parentSamplingDecision); } else { From 69877ee946e51d523835a87d444abe36edfcaf85 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 5 Jul 2024 16:00:30 +0200 Subject: [PATCH 7/7] refactor: use sampling decision --- .../src/main/java/io/sentry/opentelemetry/SentrySampler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java index b170fdb8a56..eaed924bfa8 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java +++ b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java @@ -116,7 +116,7 @@ public SamplingResult shouldSample( final @Nullable TracesSamplingDecision parentSamplingDecision = parentSentrySpan.getSamplingDecision(); if (parentSamplingDecision != null) { - if (!parentSentrySpan.isSampled()) { + if (!parentSamplingDecision.getSampled()) { scopes .getOptions() .getClientReportRecorder()