Skip to content

Commit 8f62960

Browse files
authored
enh: propagate sample seed in baggage (#2629)
* initial seed propagation impl * update * improve naming * update CHANGELOG
1 parent 8c9f280 commit 8f62960

10 files changed

+67
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Enhancements
66

7+
- Propagate sample seed in baggage header ([#2629](https://github.com/getsentry/sentry-dart/pull/2629))
8+
- Read more about the specs [here](https://develop.sentry.dev/sdk/telemetry/traces/#propagated-random-value)
79
- Finish and start new transaction when tapping same element again ([#2623](https://github.com/getsentry/sentry-dart/pull/2623))
810

911
### Fixes

dart/lib/src/sentry_baggage.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import 'package:meta/meta.dart';
2-
import 'scope.dart';
32
import 'protocol.dart';
4-
3+
import 'scope.dart';
54
import 'sentry_options.dart';
65

76
class SentryBaggage {
87
static const String _sampleRateKeyName = 'sentry-sample_rate';
8+
static const String _sampleRandKeyName = 'sentry-sample_rand';
9+
910
static const int _maxChars = 8192;
1011
static const int _maxListMember = 64;
1112

@@ -194,6 +195,10 @@ class SentryBaggage {
194195
set(_sampleRateKeyName, value);
195196
}
196197

198+
void setSampleRand(String value) {
199+
set(_sampleRandKeyName, value);
200+
}
201+
197202
void setSampled(String value) {
198203
set('sentry-sampled', value);
199204
}
@@ -207,6 +212,15 @@ class SentryBaggage {
207212
return double.tryParse(sampleRate);
208213
}
209214

215+
double? getSampleRand() {
216+
final sampleRand = get(_sampleRandKeyName);
217+
if (sampleRand == null) {
218+
return null;
219+
}
220+
221+
return double.tryParse(sampleRand);
222+
}
223+
210224
void setReplayId(String value) => set('sentry-replay_id', value);
211225

212226
SentryId? getReplayId() {

dart/lib/src/sentry_trace_context_header.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:meta/meta.dart';
22

3-
import 'protocol/sentry_id.dart';
43
import 'protocol/access_aware_map.dart';
4+
import 'protocol/sentry_id.dart';
55
import 'sentry_baggage.dart';
66
import 'sentry_options.dart';
77

@@ -15,6 +15,7 @@ class SentryTraceContextHeader {
1515
this.userSegment,
1616
this.transaction,
1717
this.sampleRate,
18+
this.sampleRand,
1819
this.sampled,
1920
this.unknown,
2021
this.replayId,
@@ -30,6 +31,7 @@ class SentryTraceContextHeader {
3031
final String? userSegment;
3132
final String? transaction;
3233
final String? sampleRate;
34+
final String? sampleRand;
3335
final String? sampled;
3436

3537
@internal
@@ -102,6 +104,9 @@ class SentryTraceContextHeader {
102104
if (sampleRate != null) {
103105
baggage.setSampleRate(sampleRate!);
104106
}
107+
if (sampleRand != null) {
108+
baggage.setSampleRand(sampleRand!);
109+
}
105110
if (sampled != null) {
106111
baggage.setSampled(sampled!);
107112
}
@@ -113,6 +118,7 @@ class SentryTraceContextHeader {
113118

114119
factory SentryTraceContextHeader.fromBaggage(SentryBaggage baggage) {
115120
return SentryTraceContextHeader(
121+
// TODO: implement and use proper get methods here
116122
SentryId.fromId(baggage.get('sentry-trace_id').toString()),
117123
baggage.get('sentry-public_key').toString(),
118124
release: baggage.get('sentry-release'),

dart/lib/src/sentry_tracer.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ class SentryTracer extends ISentrySpan {
385385
transaction:
386386
_isHighQualityTransactionName(transactionNameSource) ? name : null,
387387
sampleRate: _sampleRateToString(_rootSpan.samplingDecision?.sampleRate),
388+
sampleRand: _sampleRandToString(_rootSpan.samplingDecision?.sampleRand),
388389
sampled: _rootSpan.samplingDecision?.sampled.toString(),
389390
);
390391

@@ -398,6 +399,13 @@ class SentryTracer extends ISentrySpan {
398399
return sampleRate != null ? SampleRateFormat().format(sampleRate) : null;
399400
}
400401

402+
String? _sampleRandToString(double? sampleRand) {
403+
if (!isValidSampleRand(sampleRand)) {
404+
return null;
405+
}
406+
return sampleRand != null ? SampleRateFormat().format(sampleRand) : null;
407+
}
408+
401409
bool _isHighQualityTransactionName(SentryTransactionNameSource source) {
402410
return source != SentryTransactionNameSource.url;
403411
}

dart/lib/src/sentry_traces_sampler.dart

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,9 @@ class SentryTracesSampler {
3131
final tracesSampler = _options.tracesSampler;
3232
if (tracesSampler != null) {
3333
try {
34-
final result = tracesSampler(samplingContext);
35-
if (result != null) {
36-
return SentryTracesSamplingDecision(
37-
_sample(result),
38-
sampleRate: result,
39-
);
34+
final sampleRate = tracesSampler(samplingContext);
35+
if (sampleRate != null) {
36+
return _makeSampleDecision(sampleRate);
4037
}
4138
} catch (exception, stackTrace) {
4239
_options.logger(
@@ -64,10 +61,7 @@ class SentryTracesSampler {
6461
double? optionsOrDefaultRate = optionsRate ?? defaultRate;
6562

6663
if (optionsOrDefaultRate != null) {
67-
return SentryTracesSamplingDecision(
68-
_sample(optionsOrDefaultRate),
69-
sampleRate: optionsOrDefaultRate,
70-
);
64+
return _makeSampleDecision(optionsOrDefaultRate);
7165
}
7266

7367
return SentryTracesSamplingDecision(false);
@@ -78,8 +72,18 @@ class SentryTracesSampler {
7872
if (optionsRate == null || !tracesSamplingDecision.sampled) {
7973
return false;
8074
}
81-
return _sample(optionsRate);
75+
return _isSampled(optionsRate);
8276
}
8377

84-
bool _sample(double result) => !(result < _random.nextDouble());
78+
SentryTracesSamplingDecision _makeSampleDecision(double sampleRate) {
79+
final sampleRand = _random.nextDouble();
80+
final sampled = _isSampled(sampleRate, sampleRand: sampleRand);
81+
return SentryTracesSamplingDecision(sampled,
82+
sampleRate: sampleRate, sampleRand: sampleRand);
83+
}
84+
85+
bool _isSampled(double sampleRate, {double? sampleRand}) {
86+
final rand = sampleRand ?? _random.nextDouble();
87+
return rand <= sampleRate;
88+
}
8589
}

dart/lib/src/sentry_traces_sampling_decision.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ class SentryTracesSamplingDecision {
22
SentryTracesSamplingDecision(
33
this.sampled, {
44
this.sampleRate,
5+
this.sampleRand,
56
});
67

78
final bool sampled;
89
final double? sampleRate;
10+
final double? sampleRand;
911
}

dart/lib/src/sentry_transaction_context.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
import 'package:meta/meta.dart';
2-
import 'sentry_trace_origins.dart';
32

43
import 'protocol.dart';
54
import 'sentry_baggage.dart';
5+
import 'sentry_trace_origins.dart';
66
import 'tracing.dart';
77

88
@immutable
99
class SentryTransactionContext extends SentrySpanContext {
1010
final String name;
11-
final SentryTracesSamplingDecision? parentSamplingDecision;
1211
final SentryTransactionNameSource? transactionNameSource;
1312
final SentryTracesSamplingDecision? samplingDecision;
13+
final SentryTracesSamplingDecision? parentSamplingDecision;
1414

1515
SentryTransactionContext(
1616
this.name,
1717
String operation, {
1818
super.description,
19-
this.parentSamplingDecision,
2019
super.traceId,
2120
super.spanId,
2221
super.parentSpanId,
2322
this.transactionNameSource,
2423
this.samplingDecision,
24+
this.parentSamplingDecision,
2525
super.origin,
2626
}) : super(
2727
operation: operation,
@@ -35,6 +35,7 @@ class SentryTransactionContext extends SentrySpanContext {
3535
SentryBaggage? baggage,
3636
}) {
3737
final sampleRate = baggage?.getSampleRate();
38+
final sampleRand = baggage?.getSampleRand();
3839
return SentryTransactionContext(
3940
name,
4041
operation,
@@ -44,6 +45,7 @@ class SentryTransactionContext extends SentrySpanContext {
4445
? SentryTracesSamplingDecision(
4546
traceHeader.sampled!,
4647
sampleRate: sampleRate,
48+
sampleRand: sampleRand,
4749
)
4850
: null,
4951
transactionNameSource:

dart/lib/src/utils/tracing_utils.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,10 @@ bool isValidSampleRate(double? sampleRate) {
8080
}
8181
return !sampleRate.isNaN && sampleRate >= 0.0 && sampleRate <= 1.0;
8282
}
83+
84+
bool isValidSampleRand(double? sampleRand) {
85+
if (sampleRand == null) {
86+
return false;
87+
}
88+
return !sampleRand.isNaN && sampleRand >= 0.0 && sampleRand < 1.0;
89+
}

dart/test/protocol/sentry_baggage_header_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void main() {
2121
baggage.setUserSegment('userSegment');
2222
baggage.setTransaction('transaction');
2323
baggage.setSampleRate('1.0');
24+
baggage.setSampleRand('0.4');
2425
baggage.setSampled('false');
2526
final replayId = SentryId.newId().toString();
2627
baggage.setReplayId(replayId);
@@ -37,6 +38,7 @@ void main() {
3738
'sentry-user_segment=userSegment,'
3839
'sentry-transaction=transaction,'
3940
'sentry-sample_rate=1.0,'
41+
'sentry-sample_rand=0.4,'
4042
'sentry-sampled=false,'
4143
'sentry-replay_id=$replayId');
4244
});

dart/test/sentry_tracer_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ void main() {
487487
SentryTracesSamplingDecision(
488488
true,
489489
sampleRate: 1.0,
490+
sampleRand: 0.8,
490491
);
491492
final _context = SentryTransactionContext(
492493
'name',
@@ -512,6 +513,7 @@ void main() {
512513
expect(newBaggage.get('sentry-user_segment'), 'segment');
513514
expect(newBaggage.get('sentry-transaction'), 'name');
514515
expect(newBaggage.get('sentry-sample_rate'), '1');
516+
expect(newBaggage.getSampleRand(), 0.8);
515517
expect(newBaggage.get('sentry-sampled'), 'true');
516518
});
517519

0 commit comments

Comments
 (0)