@@ -13,8 +13,9 @@ import 'sentry_native.dart';
13
13
// ignore: invalid_use_of_internal_member
14
14
class NativeProfilerFactory implements ProfilerFactory {
15
15
final SentryNative _native;
16
+ final ClockProvider _clock;
16
17
17
- NativeProfilerFactory (this ._native);
18
+ NativeProfilerFactory (this ._native, this ._clock );
18
19
19
20
static void attachTo (Hub hub) {
20
21
// ignore: invalid_use_of_internal_member
@@ -32,24 +33,26 @@ class NativeProfilerFactory implements ProfilerFactory {
32
33
if (options.platformChecker.platform.isMacOS ||
33
34
options.platformChecker.platform.isIOS) {
34
35
// ignore: invalid_use_of_internal_member
35
- hub.profilerFactory = NativeProfilerFactory (SentryNative ());
36
+ hub.profilerFactory =
37
+ // ignore: invalid_use_of_internal_member
38
+ NativeProfilerFactory (SentryNative (), options.clock);
36
39
}
37
40
}
38
41
39
42
@override
40
- NativeProfiler ? startProfiling (SentryTransactionContext context) {
43
+ NativeProfiler ? startProfiler (SentryTransactionContext context) {
41
44
if (context.traceId == SentryId .empty ()) {
42
45
return null ;
43
46
}
44
47
45
- final startTime = _native.startProfiling (context.traceId);
48
+ final startTime = _native.startProfiler (context.traceId);
46
49
47
50
// TODO we cannot await the future returned by a method channel because
48
51
// startTransaction() is synchronous. In order to make this code fully
49
52
// synchronous and actually start the profiler, we need synchronous FFI
50
53
// calls, see https://github.com/getsentry/sentry-dart/issues/1444
51
54
// For now, return immediately even though the profiler may not have started yet...
52
- return NativeProfiler (_native, startTime, context.traceId);
55
+ return NativeProfiler (_native, startTime, context.traceId, _clock );
53
56
}
54
57
}
55
58
@@ -60,33 +63,45 @@ class NativeProfiler implements Profiler {
60
63
final SentryNative _native;
61
64
final Future <int ?> _startTime;
62
65
final SentryId _traceId;
66
+ bool _finished = false ;
67
+ final ClockProvider _clock;
63
68
64
- NativeProfiler (this ._native, this ._startTime, this ._traceId);
69
+ NativeProfiler (this ._native, this ._startTime, this ._traceId, this ._clock );
65
70
66
71
@override
67
72
void dispose () {
68
- // TODO expose in the cocoa SDK
69
- // _startTime.then((_) => _native.discardProfiling(this._traceId));
73
+ if (! _finished) {
74
+ _finished = true ;
75
+ _startTime.then ((_) => _native.discardProfiler (_traceId));
76
+ }
70
77
}
71
78
72
79
@override
73
80
Future <NativeProfileInfo ?> finishFor (SentryTransaction transaction) async {
74
- final starTime = await _startTime;
75
- if (starTime == null ) {
81
+ if (_finished) {
82
+ return null ;
83
+ }
84
+ _finished = true ;
85
+
86
+ final starTimeNs = await _startTime;
87
+ if (starTimeNs == null ) {
76
88
return null ;
77
89
}
78
90
79
- final payload = await _native.collectProfile (_traceId, starTime);
91
+ // ignore: invalid_use_of_internal_member
92
+ final transactionEndTime = transaction.timestamp ?? _clock ();
93
+ final duration = transactionEndTime.difference (transaction.startTimestamp);
94
+ final endTimeNs = starTimeNs + (duration.inMicroseconds * 1000 );
95
+
96
+ final payload =
97
+ await _native.collectProfile (_traceId, starTimeNs, endTimeNs);
80
98
if (payload == null ) {
81
99
return null ;
82
100
}
83
101
84
- payload["transaction" ] = < String , String ? > {
85
- "id" : transaction.eventId.toString (),
86
- "trace_id" : _traceId.toString (),
87
- "name" : transaction.transaction,
88
- // "active_thread_id" : [transaction.trace.transactionContext sentry_threadInfo].threadId
89
- };
102
+ payload["transaction" ]["id" ] = transaction.eventId.toString ();
103
+ payload["transaction" ]["trace_id" ] = _traceId.toString ();
104
+ payload["transaction" ]["name" ] = transaction.transaction;
90
105
payload["timestamp" ] = transaction.startTimestamp.toIso8601String ();
91
106
return NativeProfileInfo (payload);
92
107
}
0 commit comments