Skip to content

Commit caa9897

Browse files
committed
Fix child timestamp trimming
1 parent 5cc82a0 commit caa9897

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

dart/lib/src/sentry_tracer.dart

+20-13
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ class SentryTracer extends ISentrySpan {
4949
/// highest timestamp of child spans, trimming the duration of the
5050
/// transaction. This is useful to discard extra time in the transaction that
5151
/// is not accounted for in child spans, like what happens in the
52-
/// [SentryNavigatorObserver](https://pub.dev/documentation/sentry_flutter/latest/sentry_flutter/SentryNavigatorObserver-class.html)
53-
/// idle transactions, where we finish the transaction after a given
54-
/// "idle time" and we don't want this "idle time" to be part of the transaction.
52+
/// [SentryNavigatorObserver] idle transactions, where we finish the
53+
/// transaction after a given "idle time" and we don't want this "idle time"
54+
/// to be part of the transaction.
5555
SentryTracer(
5656
SentryTransactionContext transactionContext,
5757
this._hub, {
@@ -109,18 +109,24 @@ class SentryTracer extends ISentrySpan {
109109
}
110110

111111
var _rootEndTimestamp = commonEndTimestamp;
112+
113+
// Trim the end timestamp of the transaction to the very last timestamp of child spans
112114
if (_trimEnd && children.isNotEmpty) {
113-
final childEndTimestamps = children
114-
.where((child) => child.endTimestamp != null)
115-
.map((child) => child.endTimestamp!);
116-
117-
if (childEndTimestamps.isNotEmpty) {
118-
final oldestChildEndTimestamp =
119-
childEndTimestamps.reduce((a, b) => a.isAfter(b) ? a : b);
120-
if (_rootEndTimestamp.isAfter(oldestChildEndTimestamp)) {
121-
_rootEndTimestamp = oldestChildEndTimestamp;
115+
DateTime? latestEndTime;
116+
117+
for (var child in children) {
118+
final childEndTimestamp = child.endTimestamp;
119+
if (childEndTimestamp != null) {
120+
if (latestEndTime == null ||
121+
childEndTimestamp.isAfter(latestEndTime)) {
122+
latestEndTime = child.endTimestamp;
123+
}
122124
}
123125
}
126+
127+
if (latestEndTime != null) {
128+
_rootEndTimestamp = latestEndTime;
129+
}
124130
}
125131

126132
// the callback should run before because if the span is finished,
@@ -362,7 +368,8 @@ class SentryTracer extends ISentrySpan {
362368
Dsn.parse(_hub.options.dsn!).publicKey,
363369
release: _hub.options.release,
364370
environment: _hub.options.environment,
365-
userId: null, // because of PII not sending it for now
371+
userId: null,
372+
// because of PII not sending it for now
366373
userSegment: user?.segment,
367374
transaction:
368375
_isHighQualityTransactionName(transactionNameSource) ? name : null,

dart/test/sentry_tracer_test.dart

+22
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,28 @@ void main() {
386386
expect(sut.endTimestamp, endTimestamp);
387387
});
388388

389+
test('end trimmed to latest child end timestamp', () async {
390+
final sut = fixture.getSut(trimEnd: true);
391+
final rootEndInitial = getUtcDateTime();
392+
final childEnd1 = rootEndInitial;
393+
final childEnd2 = rootEndInitial.add(Duration(seconds: 1));
394+
final childEnd3 = rootEndInitial;
395+
396+
final childA = sut.startChild('operation-a', description: 'description');
397+
final childB = sut.startChild('operation-b', description: 'description');
398+
final childC = sut.startChild('operation-c', description: 'description');
399+
400+
await childA.finish(endTimestamp: childEnd1);
401+
await childB.finish(endTimestamp: childEnd2);
402+
await childC.finish(endTimestamp: childEnd3);
403+
404+
await sut.finish(endTimestamp: rootEndInitial);
405+
406+
expect(sut.endTimestamp, equals(childB.endTimestamp),
407+
reason:
408+
'The root end timestamp should be updated to match the latest child end timestamp.');
409+
});
410+
389411
test('does not add more spans than configured in options', () async {
390412
fixture.hub.options.maxSpans = 2;
391413
final sut = fixture.getSut();

0 commit comments

Comments
 (0)