Skip to content

Commit f8a9c45

Browse files
committed
new option ignoreStandaloneClientSpans; prefer spans created via Sentry API as fallback root
1 parent 66c10d9 commit f8a9c45

4 files changed

Lines changed: 43 additions & 3 deletions

File tree

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/InternalSemanticAttributes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ public final class InternalSemanticAttributes {
2121
public static final AttributeKey<String> BAGGAGE = AttributeKey.stringKey("sentry.baggage");
2222
public static final AttributeKey<Boolean> BAGGAGE_MUTABLE =
2323
AttributeKey.booleanKey("sentry.baggage_mutable");
24+
public static final AttributeKey<Boolean> CREATED_VIA_SENTRY_API = AttributeKey.booleanKey("sentry.is_created_via_sentry_api");
2425
}

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryWeakSpanStorage.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.sentry.opentelemetry;
22

3+
import io.opentelemetry.api.common.Attributes;
4+
import io.opentelemetry.api.trace.Span;
35
import io.opentelemetry.api.trace.SpanContext;
46
import io.opentelemetry.context.internal.shaded.WeakConcurrentMap;
57
import io.sentry.ISentryLifecycleToken;
@@ -46,12 +48,33 @@ private SentryWeakSpanStorage() {}
4648

4749
public void storeSentrySpan(
4850
final @NotNull SpanContext otelSpan, final @NotNull IOtelSpanWrapper sentrySpan) {
51+
System.out.println("storing span: " + sentrySpan.getOperation());
4952
this.sentrySpans.put(otelSpan, sentrySpan);
50-
if (sentrySpan.isRoot()) {
53+
if (shouldStoreSpanAsRootSpan(sentrySpan)) {
54+
System.out.println("storing span as last known root: " + sentrySpan.getOperation());
5155
lastKnownRootSpan = new WeakReference<>(sentrySpan);
5256
}
5357
}
5458

59+
private boolean shouldStoreSpanAsRootSpan(final @NotNull IOtelSpanWrapper sentrySpan) {
60+
if (!sentrySpan.isRoot()) {
61+
return false;
62+
}
63+
64+
final @Nullable IOtelSpanWrapper previousRootSpan = getLastKnownUnfinishedRootSpan();
65+
if (previousRootSpan == null) {
66+
return true;
67+
}
68+
69+
final @Nullable Attributes attributes = previousRootSpan.getOpenTelemetrySpanAttributes();
70+
if (attributes == null) {
71+
return true;
72+
}
73+
74+
final @Nullable Boolean isCreatedViaSentryApi = attributes.get(InternalSemanticAttributes.CREATED_VIA_SENTRY_API);
75+
return isCreatedViaSentryApi == true;
76+
}
77+
5578
public @Nullable IOtelSpanWrapper getLastKnownUnfinishedRootSpan() {
5679
final @Nullable IOtelSpanWrapper span = lastKnownRootSpan.get();
5780
if (span != null && !span.isFinished()) {

sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySampler.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,22 @@ public SamplingResult shouldSample(
6666
if (samplingDecision != null) {
6767
return new SentrySamplingResult(samplingDecision);
6868
} else {
69-
return handleRootOtelSpan(traceId, parentContext, attributes);
69+
return handleRootOtelSpan(traceId, parentContext, attributes, spanKind);
7070
}
7171
}
7272
}
7373

7474
private @NotNull SamplingResult handleRootOtelSpan(
7575
final @NotNull String traceId,
7676
final @NotNull Context parentContext,
77-
final @NotNull Attributes attributes) {
77+
final @NotNull Attributes attributes,
78+
final @NotNull SpanKind spanKind) {
7879
if (!scopes.getOptions().isTracingEnabled()) {
7980
return SamplingResult.create(SamplingDecision.RECORD_ONLY);
8081
}
82+
if (scopes.getOptions().isIgnoreStandaloneClientSpans() && SpanKind.CLIENT.equals(spanKind)) {
83+
return SamplingResult.create(SamplingDecision.DROP);
84+
}
8185
@Nullable Baggage baggage = null;
8286
@Nullable
8387
SentryTraceHeader sentryTraceHeader = parentContext.get(SentryOtelKeys.SENTRY_TRACE_KEY);

sentry/src/main/java/io/sentry/SentryOptions.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ public class SentryOptions {
568568

569569
private @NotNull ISocketTagger socketTagger = NoOpSocketTagger.getInstance();
570570

571+
private boolean ignoreStandaloneClientSpans = false;
572+
571573
/**
572574
* Adds an event processor
573575
*
@@ -2847,6 +2849,16 @@ public void setSocketTagger(final @Nullable ISocketTagger socketTagger) {
28472849
this.socketTagger = socketTagger != null ? socketTagger : NoOpSocketTagger.getInstance();
28482850
}
28492851

2852+
@ApiStatus.Experimental
2853+
public void setIgnoreStandaloneClientSpans(final boolean ignoreStandaloneClientSpans) {
2854+
this.ignoreStandaloneClientSpans = ignoreStandaloneClientSpans;
2855+
}
2856+
2857+
@ApiStatus.Experimental
2858+
public boolean isIgnoreStandaloneClientSpans() {
2859+
return ignoreStandaloneClientSpans;
2860+
}
2861+
28502862
/**
28512863
* Load the lazy fields. Useful to load in the background, so that results are already cached. DO
28522864
* NOT CALL THIS METHOD ON THE MAIN THREAD.

0 commit comments

Comments
 (0)