Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Enhancements

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

### Fixes
Expand Down
18 changes: 16 additions & 2 deletions dart/lib/src/sentry_baggage.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:meta/meta.dart';
import 'scope.dart';
import 'protocol.dart';

import 'scope.dart';
import 'sentry_options.dart';

class SentryBaggage {
static const String _sampleRateKeyName = 'sentry-sample_rate';
static const String _sampleRandKeyName = 'sentry-sample_rand';

static const int _maxChars = 8192;
static const int _maxListMember = 64;

Expand Down Expand Up @@ -194,6 +195,10 @@ class SentryBaggage {
set(_sampleRateKeyName, value);
}

void setSampleRand(String value) {
set(_sampleRandKeyName, value);
}

void setSampled(String value) {
set('sentry-sampled', value);
}
Expand All @@ -207,6 +212,15 @@ class SentryBaggage {
return double.tryParse(sampleRate);
}

double? getSampleRand() {
final sampleRand = get(_sampleRandKeyName);
if (sampleRand == null) {
return null;
}

return double.tryParse(sampleRand);
}

void setReplayId(String value) => set('sentry-replay_id', value);

SentryId? getReplayId() {
Expand Down
8 changes: 7 additions & 1 deletion dart/lib/src/sentry_trace_context_header.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:meta/meta.dart';

import 'protocol/sentry_id.dart';
import 'protocol/access_aware_map.dart';
import 'protocol/sentry_id.dart';
import 'sentry_baggage.dart';
import 'sentry_options.dart';

Expand All @@ -15,6 +15,7 @@ class SentryTraceContextHeader {
this.userSegment,
this.transaction,
this.sampleRate,
this.sampleRand,
this.sampled,
this.unknown,
this.replayId,
Expand All @@ -30,6 +31,7 @@ class SentryTraceContextHeader {
final String? userSegment;
final String? transaction;
final String? sampleRate;
final String? sampleRand;
final String? sampled;

@internal
Expand Down Expand Up @@ -102,6 +104,9 @@ class SentryTraceContextHeader {
if (sampleRate != null) {
baggage.setSampleRate(sampleRate!);
}
if (sampleRand != null) {
baggage.setSampleRand(sampleRand!);
}
if (sampled != null) {
baggage.setSampled(sampled!);
}
Expand All @@ -113,6 +118,7 @@ class SentryTraceContextHeader {

factory SentryTraceContextHeader.fromBaggage(SentryBaggage baggage) {
return SentryTraceContextHeader(
// TODO: implement and use proper get methods here
SentryId.fromId(baggage.get('sentry-trace_id').toString()),
baggage.get('sentry-public_key').toString(),
release: baggage.get('sentry-release'),
Expand Down
8 changes: 8 additions & 0 deletions dart/lib/src/sentry_tracer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ class SentryTracer extends ISentrySpan {
transaction:
_isHighQualityTransactionName(transactionNameSource) ? name : null,
sampleRate: _sampleRateToString(_rootSpan.samplingDecision?.sampleRate),
sampleRand: _sampleRandToString(_rootSpan.samplingDecision?.sampleRand),
sampled: _rootSpan.samplingDecision?.sampled.toString(),
);

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

String? _sampleRandToString(double? sampleRand) {
if (!isValidSampleRand(sampleRand)) {
return null;
}
return sampleRand != null ? SampleRateFormat().format(sampleRand) : null;
}

bool _isHighQualityTransactionName(SentryTransactionNameSource source) {
return source != SentryTransactionNameSource.url;
}
Expand Down
28 changes: 16 additions & 12 deletions dart/lib/src/sentry_traces_sampler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ class SentryTracesSampler {
final tracesSampler = _options.tracesSampler;
if (tracesSampler != null) {
try {
final result = tracesSampler(samplingContext);
if (result != null) {
return SentryTracesSamplingDecision(
_sample(result),
sampleRate: result,
);
final sampleRate = tracesSampler(samplingContext);
if (sampleRate != null) {
return _makeSampleDecision(sampleRate);
}
} catch (exception, stackTrace) {
_options.logger(
Expand Down Expand Up @@ -64,10 +61,7 @@ class SentryTracesSampler {
double? optionsOrDefaultRate = optionsRate ?? defaultRate;

if (optionsOrDefaultRate != null) {
return SentryTracesSamplingDecision(
_sample(optionsOrDefaultRate),
sampleRate: optionsOrDefaultRate,
);
return _makeSampleDecision(optionsOrDefaultRate);
}

return SentryTracesSamplingDecision(false);
Expand All @@ -78,8 +72,18 @@ class SentryTracesSampler {
if (optionsRate == null || !tracesSamplingDecision.sampled) {
return false;
}
return _sample(optionsRate);
return _isSampled(optionsRate);
}

bool _sample(double result) => !(result < _random.nextDouble());
SentryTracesSamplingDecision _makeSampleDecision(double sampleRate) {
final sampleRand = _random.nextDouble();
final sampled = _isSampled(sampleRate, sampleRand: sampleRand);
return SentryTracesSamplingDecision(sampled,
sampleRate: sampleRate, sampleRand: sampleRand);
}

bool _isSampled(double sampleRate, {double? sampleRand}) {
final rand = sampleRand ?? _random.nextDouble();
return rand <= sampleRate;
}
}
2 changes: 2 additions & 0 deletions dart/lib/src/sentry_traces_sampling_decision.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ class SentryTracesSamplingDecision {
SentryTracesSamplingDecision(
this.sampled, {
this.sampleRate,
this.sampleRand,
});

final bool sampled;
final double? sampleRate;
final double? sampleRand;
}
8 changes: 5 additions & 3 deletions dart/lib/src/sentry_transaction_context.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import 'package:meta/meta.dart';
import 'sentry_trace_origins.dart';

import 'protocol.dart';
import 'sentry_baggage.dart';
import 'sentry_trace_origins.dart';
import 'tracing.dart';

@immutable
class SentryTransactionContext extends SentrySpanContext {
final String name;
final SentryTracesSamplingDecision? parentSamplingDecision;
final SentryTransactionNameSource? transactionNameSource;
final SentryTracesSamplingDecision? samplingDecision;
final SentryTracesSamplingDecision? parentSamplingDecision;

SentryTransactionContext(
this.name,
String operation, {
super.description,
this.parentSamplingDecision,
super.traceId,
super.spanId,
super.parentSpanId,
this.transactionNameSource,
this.samplingDecision,
this.parentSamplingDecision,
super.origin,
}) : super(
operation: operation,
Expand All @@ -35,6 +35,7 @@ class SentryTransactionContext extends SentrySpanContext {
SentryBaggage? baggage,
}) {
final sampleRate = baggage?.getSampleRate();
final sampleRand = baggage?.getSampleRand();
return SentryTransactionContext(
name,
operation,
Expand All @@ -44,6 +45,7 @@ class SentryTransactionContext extends SentrySpanContext {
? SentryTracesSamplingDecision(
traceHeader.sampled!,
sampleRate: sampleRate,
sampleRand: sampleRand,
)
: null,
transactionNameSource:
Expand Down
7 changes: 7 additions & 0 deletions dart/lib/src/utils/tracing_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,10 @@ bool isValidSampleRate(double? sampleRate) {
}
return !sampleRate.isNaN && sampleRate >= 0.0 && sampleRate <= 1.0;
}

bool isValidSampleRand(double? sampleRand) {
if (sampleRand == null) {
return false;
}
return !sampleRand.isNaN && sampleRand >= 0.0 && sampleRand < 1.0;
}
2 changes: 2 additions & 0 deletions dart/test/protocol/sentry_baggage_header_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void main() {
baggage.setUserSegment('userSegment');
baggage.setTransaction('transaction');
baggage.setSampleRate('1.0');
baggage.setSampleRand('0.4');
baggage.setSampled('false');
final replayId = SentryId.newId().toString();
baggage.setReplayId(replayId);
Expand All @@ -37,6 +38,7 @@ void main() {
'sentry-user_segment=userSegment,'
'sentry-transaction=transaction,'
'sentry-sample_rate=1.0,'
'sentry-sample_rand=0.4,'
'sentry-sampled=false,'
'sentry-replay_id=$replayId');
});
Expand Down
2 changes: 2 additions & 0 deletions dart/test/sentry_tracer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ void main() {
SentryTracesSamplingDecision(
true,
sampleRate: 1.0,
sampleRand: 0.8,
);
final _context = SentryTransactionContext(
'name',
Expand All @@ -512,6 +513,7 @@ void main() {
expect(newBaggage.get('sentry-user_segment'), 'segment');
expect(newBaggage.get('sentry-transaction'), 'name');
expect(newBaggage.get('sentry-sample_rate'), '1');
expect(newBaggage.getSampleRand(), 0.8);
expect(newBaggage.get('sentry-sampled'), 'true');
});

Expand Down
Loading