Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor committed Jun 13, 2024
1 parent cb8e94f commit 2219ec3
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 14 deletions.
2 changes: 1 addition & 1 deletion dart/lib/src/performance_collector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ abstract class PerformanceCollector {}
abstract class PerformanceContinuousCollector extends PerformanceCollector {
void onSpanStarted(ISentrySpan span);

void onSpanFinished(ISentrySpan span);
void onSpanFinished(ISentrySpan span, DateTime endTimestamp);

void clear();
}
14 changes: 9 additions & 5 deletions dart/lib/src/protocol/sentry_span.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import 'dart:async';

import '../../sentry.dart';
import '../hub.dart';
import '../metrics/local_metrics_aggregator.dart';
import '../protocol.dart';

import '../sentry_tracer.dart';
import '../tracing.dart';
import '../utils.dart';

typedef OnFinishedCallback = Future<void> Function({DateTime? endTimestamp});

Expand All @@ -17,6 +13,9 @@ class SentrySpan extends ISentrySpan {
Map<String, List<MetricSummary>>? _metricSummaries;
late final DateTime _startTimestamp;
final Hub _hub;
bool _isRootSpan = false;

bool get isRootSpan => _isRootSpan;

final SentryTracer _tracer;
final Map<String, dynamic> _data = {};
Expand All @@ -37,13 +36,15 @@ class SentrySpan extends ISentrySpan {
DateTime? startTimestamp,
this.samplingDecision,
OnFinishedCallback? finishedCallback,
isRootSpan = false,
}) {
_startTimestamp = startTimestamp?.toUtc() ?? _hub.options.clock();
_finishedCallback = finishedCallback;
_origin = _context.origin;
_localMetricsAggregator = _hub.options.enableSpanLocalMetricAggregation
? LocalMetricsAggregator()
: null;
_isRootSpan = isRootSpan;
}

@override
Expand Down Expand Up @@ -71,7 +72,10 @@ class SentrySpan extends ISentrySpan {
// We need the timestamp so we can finish here
for (final collector in _hub.options.performanceCollectors) {
if (collector is PerformanceContinuousCollector) {
collector.onSpanFinished(this);
final _timestamp = _endTimestamp;
if (_timestamp != null) {
collector.onSpanFinished(this, _timestamp);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions dart/lib/src/sentry_tracer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class SentryTracer extends ISentrySpan {
_hub,
samplingDecision: transactionContext.samplingDecision,
startTimestamp: startTimestamp,
isRootSpan: true,
);
_waitForChildren = waitForChildren;
_autoFinishAfter = autoFinishAfter;
Expand Down Expand Up @@ -127,6 +128,12 @@ class SentryTracer extends ISentrySpan {
}
}

for (final collector in _hub.options.performanceCollectors) {
if (collector is PerformanceContinuousCollector) {
collector.onSpanFinished(this, _rootEndTimestamp);
}
}

// the callback should run before because if the span is finished,
// we cannot attach data, its immutable after being finished.
final finish = _onFinish?.call(this);
Expand Down
12 changes: 7 additions & 5 deletions flutter/lib/src/span_frame_metrics_collector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SpanFrameMetricsCollector implements PerformanceContinuousCollector {
final frames = SplayTreeMap<DateTime, int>();
final runningSpans = <ISentrySpan>[];

bool get isFrameTrackingPaused => _isFrameTrackingPaused;
bool _isFrameTrackingPaused = true;
bool _isFrameTrackingRegistered = false;

Expand All @@ -40,12 +41,14 @@ class SpanFrameMetricsCollector implements PerformanceContinuousCollector {
}

@override
void onSpanFinished(ISentrySpan span) {
if (span is NoOpSentrySpan || !options.enableFramesTracking) {
void onSpanFinished(ISentrySpan span, DateTime endTimestamp) {
if ((span is SentrySpan) && span.isRootSpan ||
span is NoOpSentrySpan ||
!options.enableFramesTracking) {
return;
}

captureFrameMetrics(span);
captureFrameMetrics(span, endTimestamp);

if (runningSpans.isEmpty) {
clear();
Expand All @@ -54,11 +57,10 @@ class SpanFrameMetricsCollector implements PerformanceContinuousCollector {
}
}

void captureFrameMetrics(ISentrySpan span) {
void captureFrameMetrics(ISentrySpan span, DateTime endTimestamp) {
runningSpans.removeWhere(
(element) => element.context.spanId == span.context.spanId);

final endTimestamp = span.endTimestamp;
if (endTimestamp == null) {
// todo: log
return;
Expand Down
35 changes: 32 additions & 3 deletions flutter/test/span_frame_metrics_collector_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ void main() {
.map((duration) => _isWithinRange(duration.inMilliseconds))));
});

test('captureFrameMetrics calculates frame metrics correctly', () async {
test('captureFrameMetrics calculates frame metrics correctly for trace',
() async {
final sut = fixture.sut;
fixture.options.tracesSampleRate = 1.0;
fixture.options.addPerformanceCollector(sut);

final tracer =
SentryTracer(SentryTransactionContext('name', 'op'), fixture.hub);

final child = tracer.startChild('child') as SentrySpan;

await Future<void>.delayed(Duration(milliseconds: 800));
Expand All @@ -57,10 +57,39 @@ void main() {

// The expected total frames is based on the span duration and the slow and frozen frames
const expectedTotalFrames = 4;

expect(tracer.data['frames.slow'], 2);
expect(tracer.data['frames.frozen'], 1);
expect(
tracer.data['frames.delay'], _isWithinRange(expectedFramesDelay, 10));
expect(tracer.data['frames.total'], _isWithinRange(expectedTotalFrames, 2));

expect(tracer.measurements['frames_delay']!.value,
_isWithinRange(expectedFramesDelay, 10));
expect(tracer.measurements['frames_total']!.value,
_isWithinRange(expectedTotalFrames, 2));
expect(tracer.measurements['frames_slow']!.value, 2);
expect(tracer.measurements['frames_frozen']!.value, 1);

expect(child.data['frames.slow'], 2);
expect(child.data['frames.frozen'], 1);
expect(child.data['frames.delay'], _isWithinRange(expectedFramesDelay, 10));
expect(child.data['frames.total'], _isWithinRange(expectedTotalFrames, 1));
expect(child.data['frames.total'], _isWithinRange(expectedTotalFrames, 2));
});

test('frame tracker is paused after finishing a span', () async {
final sut = fixture.sut;
fixture.options.tracesSampleRate = 1.0;
fixture.options.addPerformanceCollector(sut);

final tracer =
SentryTracer(SentryTransactionContext('name', 'op'), fixture.hub);

await Future<void>.delayed(Duration(milliseconds: 800));

await tracer.finish();

expect(sut.isFrameTrackingPaused, isTrue);
});
}

Expand Down

0 comments on commit 2219ec3

Please sign in to comment.