Skip to content

Commit dc85168

Browse files
Propagate sampling random value (#4153)
* wip * wip2 * wip3 * format + api * cleanup * revert change to demo * make baggage final again * remove ObjectToString suppressing * remove outdated comment * remove getPropagationContext from Scopes again * remove noop baggage and propagation context again * fix outbox sender; test; cleanup api file * review changes * fix test for old span processor * review feedback * Format code * changelog --------- Co-authored-by: Sentry Github Bot <bot+github-bot@sentry.io>
1 parent 367d8b9 commit dc85168

39 files changed

+881
-213
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
- Expose new `withSentryObservableEffect` method overload that accepts `SentryNavigationListener` as a parameter ([#4143](https://github.com/getsentry/sentry-java/pull/4143))
1414
- This allows sharing the same `SentryNavigationListener` instance across fragments and composables to preserve the trace
1515
- (Internal) Add API to filter native debug images based on stacktrace addresses ([#4089](https://github.com/getsentry/sentry-java/pull/4089))
16+
- Propagate sampling random value ([#4153](https://github.com/getsentry/sentry-java/pull/4153))
17+
- The random value used for sampling traces is now sent to Sentry and attached to the `baggage` header on outgoing requests
1618

1719
### Fixes
1820

sentry-opentelemetry/sentry-opentelemetry-bootstrap/api/sentry-opentelemetry-bootstrap.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public final class io/sentry/opentelemetry/InternalSemanticAttributes {
2020
public static final field PROFILE_SAMPLED Lio/opentelemetry/api/common/AttributeKey;
2121
public static final field PROFILE_SAMPLE_RATE Lio/opentelemetry/api/common/AttributeKey;
2222
public static final field SAMPLED Lio/opentelemetry/api/common/AttributeKey;
23+
public static final field SAMPLE_RAND Lio/opentelemetry/api/common/AttributeKey;
2324
public static final field SAMPLE_RATE Lio/opentelemetry/api/common/AttributeKey;
2425
public fun <init> ()V
2526
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public final class InternalSemanticAttributes {
88
public static final AttributeKey<Boolean> SAMPLED = AttributeKey.booleanKey("sentry.sampled");
99
public static final AttributeKey<Double> SAMPLE_RATE =
1010
AttributeKey.doubleKey("sentry.sample_rate");
11+
public static final AttributeKey<Double> SAMPLE_RAND =
12+
AttributeKey.doubleKey("sentry.sample_rand");
1113
public static final AttributeKey<Boolean> PARENT_SAMPLED =
1214
AttributeKey.booleanKey("sentry.parent_sampled");
1315
public static final AttributeKey<Boolean> PROFILE_SAMPLED =

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ public OtelSpanFactory() {
136136
spanBuilder.setAttribute(InternalSemanticAttributes.SAMPLED, samplingDecision.getSampled());
137137
spanBuilder.setAttribute(
138138
InternalSemanticAttributes.SAMPLE_RATE, samplingDecision.getSampleRate());
139+
spanBuilder.setAttribute(
140+
InternalSemanticAttributes.SAMPLE_RAND, samplingDecision.getSampleRand());
139141
spanBuilder.setAttribute(
140142
InternalSemanticAttributes.PROFILE_SAMPLED, samplingDecision.getProfileSampled());
141143
spanBuilder.setAttribute(

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ public final class OtelSamplingUtil {
1414
final @Nullable Boolean sampled = attributes.get(InternalSemanticAttributes.SAMPLED);
1515
if (sampled != null) {
1616
final @Nullable Double sampleRate = attributes.get(InternalSemanticAttributes.SAMPLE_RATE);
17+
final @Nullable Double sampleRand = attributes.get(InternalSemanticAttributes.SAMPLE_RAND);
1718
final @Nullable Boolean profileSampled =
1819
attributes.get(InternalSemanticAttributes.PROFILE_SAMPLED);
1920
final @Nullable Double profileSampleRate =
2021
attributes.get(InternalSemanticAttributes.PROFILE_SAMPLE_RATE);
2122

2223
return new TracesSamplingDecision(
23-
sampled, sampleRate, profileSampled == null ? false : profileSampled, profileSampleRate);
24+
sampled,
25+
sampleRate,
26+
sampleRand,
27+
profileSampled == null ? false : profileSampled,
28+
profileSampleRate);
2429
} else {
2530
return null;
2631
}

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
import io.sentry.Baggage;
1414
import io.sentry.BaggageHeader;
1515
import io.sentry.IScopes;
16-
import io.sentry.PropagationContext;
1716
import io.sentry.ScopesAdapter;
1817
import io.sentry.Sentry;
1918
import io.sentry.SentryLevel;
2019
import io.sentry.SentryTraceHeader;
2120
import io.sentry.exception.InvalidSentryTraceHeaderException;
21+
import io.sentry.util.TracingUtils;
2222
import java.util.Arrays;
2323
import java.util.Collection;
2424
import java.util.Collections;
@@ -73,12 +73,17 @@ public <C> void inject(final Context context, final C carrier, final TextMapSett
7373
return;
7474
}
7575

76-
final @NotNull SentryTraceHeader sentryTraceHeader = sentrySpan.toSentryTrace();
77-
setter.set(carrier, sentryTraceHeader.getName(), sentryTraceHeader.getValue());
78-
final @Nullable BaggageHeader baggageHeader =
79-
sentrySpan.toBaggageHeader(Collections.emptyList());
80-
if (baggageHeader != null) {
81-
setter.set(carrier, baggageHeader.getName(), baggageHeader.getValue());
76+
// TODO can we use traceIfAllowed? do we have the URL here? need to access span attrs
77+
final @Nullable TracingUtils.TracingHeaders tracingHeaders =
78+
TracingUtils.trace(scopes, Collections.emptyList(), sentrySpan);
79+
80+
if (tracingHeaders != null) {
81+
final @NotNull SentryTraceHeader sentryTraceHeader = tracingHeaders.getSentryTraceHeader();
82+
setter.set(carrier, sentryTraceHeader.getName(), sentryTraceHeader.getValue());
83+
final @Nullable BaggageHeader baggageHeader = tracingHeaders.getBaggageHeader();
84+
if (baggageHeader != null) {
85+
setter.set(carrier, baggageHeader.getName(), baggageHeader.getValue());
86+
}
8287
}
8388
}
8489

@@ -125,11 +130,6 @@ public <C> Context extract(
125130
.getLogger()
126131
.log(SentryLevel.DEBUG, "Continuing Sentry trace %s", sentryTraceHeader.getTraceId());
127132

128-
final @NotNull PropagationContext propagationContext =
129-
PropagationContext.fromHeaders(
130-
scopes.getOptions().getLogger(), sentryTraceString, baggageString);
131-
scopesToUse.getIsolationScope().setPropagationContext(propagationContext);
132-
133133
return modifiedContext;
134134
} catch (InvalidSentryTraceHeaderException e) {
135135
scopes

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,10 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri
7070
baggage = baggageFromContext;
7171
}
7272

73-
final @Nullable Boolean baggageMutable =
74-
otelSpan.getAttribute(InternalSemanticAttributes.BAGGAGE_MUTABLE);
7573
final @Nullable String baggageString =
7674
otelSpan.getAttribute(InternalSemanticAttributes.BAGGAGE);
7775
if (baggageString != null) {
7876
baggage = Baggage.fromHeader(baggageString);
79-
if (baggageMutable == true) {
80-
baggage.freeze();
81-
}
8277
}
8378

8479
final @Nullable Boolean sampled = isSampled(otelSpan, samplingDecision);
@@ -87,6 +82,8 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri
8782
new PropagationContext(
8883
new SentryId(traceId), sentrySpanId, sentryParentSpanId, baggage, sampled);
8984

85+
baggage = propagationContext.getBaggage();
86+
9087
updatePropagationContext(scopes, propagationContext);
9188
}
9289

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

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ public final class OtelSpanWrapper implements IOtelSpanWrapper {
6464
private final @NotNull Contexts contexts = new Contexts();
6565
private @Nullable String transactionName;
6666
private @Nullable TransactionNameSource transactionNameSource;
67-
private final @Nullable Baggage baggage;
6867
private final @NotNull AutoClosableReentrantLock lock = new AutoClosableReentrantLock();
6968

7069
private final @NotNull Map<String, Object> data = new ConcurrentHashMap<>();
@@ -86,17 +85,12 @@ public OtelSpanWrapper(
8685
this.scopes = Objects.requireNonNull(scopes, "scopes are required");
8786
this.span = new WeakReference<>(span);
8887
this.startTimestamp = startTimestamp;
89-
90-
if (parentSpan != null) {
91-
this.baggage = parentSpan.getSpanContext().getBaggage();
92-
} else if (baggage != null) {
93-
this.baggage = baggage;
94-
} else {
95-
this.baggage = null;
96-
}
97-
88+
final @Nullable Baggage baggageToUse =
89+
baggage != null
90+
? baggage
91+
: (parentSpan != null ? parentSpan.getSpanContext().getBaggage() : null);
9892
this.context =
99-
new OtelSpanContext(span, samplingDecision, parentSpan, parentSpanId, this.baggage);
93+
new OtelSpanContext(span, samplingDecision, parentSpan, parentSpanId, baggageToUse);
10094
}
10195

10296
@Override
@@ -207,15 +201,16 @@ public OtelSpanWrapper(
207201
@Override
208202
public @Nullable TraceContext traceContext() {
209203
if (scopes.getOptions().isTraceSampling()) {
204+
final @Nullable Baggage baggage = context.getBaggage();
210205
if (baggage != null) {
211-
updateBaggageValues();
206+
updateBaggageValues(baggage);
212207
return baggage.toTraceContext();
213208
}
214209
}
215210
return null;
216211
}
217212

218-
private void updateBaggageValues() {
213+
private void updateBaggageValues(final @NotNull Baggage baggage) {
219214
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
220215
if (baggage != null && baggage.isMutable()) {
221216
final AtomicReference<SentryId> replayIdAtomicReference = new AtomicReference<>();
@@ -238,8 +233,9 @@ private void updateBaggageValues() {
238233
@Override
239234
public @Nullable BaggageHeader toBaggageHeader(@Nullable List<String> thirdPartyBaggageHeaders) {
240235
if (scopes.getOptions().isTraceSampling()) {
236+
final @Nullable Baggage baggage = context.getBaggage();
241237
if (baggage != null) {
242-
updateBaggageValues();
238+
updateBaggageValues(baggage);
243239
return BaggageHeader.fromBaggageAndOutgoingHeader(baggage, thirdPartyBaggageHeaders);
244240
}
245241
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ public SamplingResult shouldSample(
9595
scopes
9696
.getOptions()
9797
.getInternalTracesSampler()
98-
.sample(new SamplingContext(transactionContext, null));
98+
.sample(
99+
new SamplingContext(transactionContext, null, propagationContext.getSampleRand()));
99100

100101
if (!sentryDecision.getSampled()) {
101102
scopes

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public Attributes getAttributes() {
2929
return Attributes.builder()
3030
.put(InternalSemanticAttributes.SAMPLED, sentryDecision.getSampled())
3131
.put(InternalSemanticAttributes.SAMPLE_RATE, sentryDecision.getSampleRate())
32+
.put(InternalSemanticAttributes.SAMPLE_RAND, sentryDecision.getSampleRand())
3233
.put(InternalSemanticAttributes.PROFILE_SAMPLED, sentryDecision.getProfileSampled())
3334
.put(InternalSemanticAttributes.PROFILE_SAMPLE_RATE, sentryDecision.getProfileSampleRate())
3435
.build();

0 commit comments

Comments
 (0)