Skip to content

Commit f66df95

Browse files
committed
update to the latest cocoa SDK API
1 parent 2620276 commit f66df95

14 files changed

+513
-134
lines changed

dart/lib/src/hub.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ class Hub {
455455
Profiler? profiler;
456456
if (_profilerFactory != null &&
457457
_tracesSampler.sampleProfiling(samplingDecision)) {
458-
profiler = _profilerFactory?.startProfiling(transactionContext);
458+
profiler = _profilerFactory?.startProfiler(transactionContext);
459459
}
460460

461461
final tracer = SentryTracer(

dart/lib/src/profiling.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import '../sentry.dart';
66

77
@internal
88
abstract class ProfilerFactory {
9-
Profiler? startProfiling(SentryTransactionContext context);
9+
Profiler? startProfiler(SentryTransactionContext context);
1010
}
1111

1212
@internal

dart/lib/src/protocol/sentry_event.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class SentryEvent with SentryEventLike<SentryEvent> {
5959
/// The ID Sentry.io assigned to the submitted event for future reference.
6060
final SentryId eventId;
6161

62-
/// A timestamp representing when the breadcrumb occurred.
62+
/// A timestamp representing when the event occurred.
6363
final DateTime? timestamp;
6464

6565
/// A string representing the platform the SDK is submitting from. This will be used by the Sentry interface to customize various components in the interface.

dart/test/hub_test.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ void main() {
387387
test('profiler is started according to the sampling rate', () async {
388388
final hub = fixture.getSut();
389389
final factory = MockProfilerFactory();
390-
when(factory.startProfiling(fixture._context)).thenReturn(MockProfiler());
390+
when(factory.startProfiler(fixture._context)).thenReturn(MockProfiler());
391391
hub.profilerFactory = factory;
392392

393393
var tr = hub.startTransactionWithContext(fixture._context);
@@ -397,15 +397,15 @@ void main() {
397397
hub.options.profilesSampleRate = 1.0;
398398
tr = hub.startTransactionWithContext(fixture._context);
399399
expect((tr as SentryTracer).profiler, isNotNull);
400-
verify(factory.startProfiling(fixture._context)).called(1);
400+
verify(factory.startProfiler(fixture._context)).called(1);
401401
});
402402

403403
test('profiler.finish() is called', () async {
404404
final hub = fixture.getSut();
405405
final factory = MockProfilerFactory();
406406
final profiler = MockProfiler();
407407
final expected = MockProfileInfo();
408-
when(factory.startProfiling(fixture._context)).thenReturn(profiler);
408+
when(factory.startProfiler(fixture._context)).thenReturn(profiler);
409409
when(profiler.finishFor(any)).thenAnswer((_) async => expected);
410410

411411
hub.profilerFactory = factory;
@@ -421,7 +421,7 @@ void main() {
421421
final factory = MockProfilerFactory();
422422
final profiler = MockProfiler();
423423
final expected = MockProfileInfo();
424-
when(factory.startProfiling(fixture._context)).thenReturn(profiler);
424+
when(factory.startProfiler(fixture._context)).thenReturn(profiler);
425425
when(profiler.finishFor(any)).thenAnswer((_) async => expected);
426426

427427
hub.profilerFactory = factory;

dart/test/mocks.mocks.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ class MockProfilerFactory extends _i1.Mock implements _i3.ProfilerFactory {
4040
}
4141

4242
@override
43-
_i3.Profiler? startProfiling(_i2.SentryTransactionContext? context) =>
43+
_i3.Profiler? startProfiler(_i2.SentryTransactionContext? context) =>
4444
(super.noSuchMethod(Invocation.method(
45-
#startProfiling,
45+
#startProfiler,
4646
[context],
4747
)) as _i3.Profiler?);
4848
}

flutter/ios/Classes/SentryFlutterPluginApple.swift

+25-5
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,11 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin {
153153
removeTag(key: key, result: result)
154154

155155
#if !os(tvOS) && !os(watchOS)
156-
case "startProfiling":
157-
startProfiling(call, result)
156+
case "startProfiler":
157+
startProfiler(call, result)
158+
159+
case "discardProfiler":
160+
discardProfiler(call, result)
158161

159162
case "collectProfile":
160163
collectProfile(call, result)
@@ -559,14 +562,14 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin {
559562
}
560563
}
561564

562-
private func startProfiling(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
565+
private func startProfiler(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
563566
guard let traceId = call.arguments as? String else {
564567
print("Cannot start profiling: trace ID missing")
565568
result(FlutterError(code: "5", message: "Cannot start profiling: trace ID missing", details: nil))
566569
return
567570
}
568571

569-
let startTime = PrivateSentrySDKOnly.startProfiling(forTrace: SentryId(uuidString: traceId))
572+
let startTime = PrivateSentrySDKOnly.startProfiler(forTrace: SentryId(uuidString: traceId))
570573
result(startTime)
571574
}
572575

@@ -584,9 +587,26 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin {
584587
return
585588
}
586589

587-
let payload = PrivateSentrySDKOnly.collectProfile(forTrace: SentryId(uuidString: traceId), since: startTime)
590+
guard let endTime = arguments["endTime"] as? UInt64 else {
591+
print("Cannot collect profile: end time missing")
592+
result(FlutterError(code: "8", message: "Cannot collect profile: end time missing", details: nil))
593+
return
594+
}
595+
596+
let payload = PrivateSentrySDKOnly.collectProfileBetween(startTime, and: endTime, forTrace: SentryId(uuidString: traceId))
588597
result(payload)
589598
}
599+
600+
private func discardProfiler(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
601+
guard let traceId = call.arguments as? String else {
602+
print("Cannot discard a profiler: trace ID missing")
603+
result(FlutterError(code: "9", message: "Cannot discard a profiler: trace ID missing", details: nil))
604+
return
605+
}
606+
607+
PrivateSentrySDKOnly.discardProfiler(forTrace: SentryId(uuidString: traceId))
608+
result(nil)
609+
}
590610
}
591611

592612
// swiftlint:enable function_body_length

flutter/lib/src/profiling.dart

+32-17
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ import 'sentry_native.dart';
1313
// ignore: invalid_use_of_internal_member
1414
class NativeProfilerFactory implements ProfilerFactory {
1515
final SentryNative _native;
16+
final ClockProvider _clock;
1617

17-
NativeProfilerFactory(this._native);
18+
NativeProfilerFactory(this._native, this._clock);
1819

1920
static void attachTo(Hub hub) {
2021
// ignore: invalid_use_of_internal_member
@@ -32,24 +33,26 @@ class NativeProfilerFactory implements ProfilerFactory {
3233
if (options.platformChecker.platform.isMacOS ||
3334
options.platformChecker.platform.isIOS) {
3435
// 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);
3639
}
3740
}
3841

3942
@override
40-
NativeProfiler? startProfiling(SentryTransactionContext context) {
43+
NativeProfiler? startProfiler(SentryTransactionContext context) {
4144
if (context.traceId == SentryId.empty()) {
4245
return null;
4346
}
4447

45-
final startTime = _native.startProfiling(context.traceId);
48+
final startTime = _native.startProfiler(context.traceId);
4649

4750
// TODO we cannot await the future returned by a method channel because
4851
// startTransaction() is synchronous. In order to make this code fully
4952
// synchronous and actually start the profiler, we need synchronous FFI
5053
// calls, see https://github.com/getsentry/sentry-dart/issues/1444
5154
// 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);
5356
}
5457
}
5558

@@ -60,33 +63,45 @@ class NativeProfiler implements Profiler {
6063
final SentryNative _native;
6164
final Future<int?> _startTime;
6265
final SentryId _traceId;
66+
bool _finished = false;
67+
final ClockProvider _clock;
6368

64-
NativeProfiler(this._native, this._startTime, this._traceId);
69+
NativeProfiler(this._native, this._startTime, this._traceId, this._clock);
6570

6671
@override
6772
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+
}
7077
}
7178

7279
@override
7380
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) {
7688
return null;
7789
}
7890

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);
8098
if (payload == null) {
8199
return null;
82100
}
83101

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;
90105
payload["timestamp"] = transaction.startTimestamp.toIso8601String();
91106
return NativeProfileInfo(payload);
92107
}

flutter/lib/src/sentry_native.dart

+8-4
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ class SentryNative {
9292
return await _nativeChannel?.removeTag(key);
9393
}
9494

95-
Future<int?> startProfiling(SentryId traceId) async {
96-
return _nativeChannel?.startProfiling(traceId);
95+
Future<int?> startProfiler(SentryId traceId) async {
96+
return _nativeChannel?.startProfiler(traceId);
97+
}
98+
99+
Future<void> discardProfiler(SentryId traceId) async {
100+
return _nativeChannel?.discardProfiler(traceId);
97101
}
98102

99103
Future<Map<String, dynamic>?> collectProfile(
100-
SentryId traceId, int startTimeNs) async {
101-
return _nativeChannel?.collectProfile(traceId, startTimeNs);
104+
SentryId traceId, int startTimeNs, int endTimeNs) async {
105+
return _nativeChannel?.collectProfile(traceId, startTimeNs, endTimeNs);
102106
}
103107

104108
/// Reset state

flutter/lib/src/sentry_native_channel.dart

+17-6
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,32 @@ class SentryNativeChannel {
138138
}
139139
}
140140

141-
Future<int?> startProfiling(SentryId traceId) async {
141+
Future<int?> startProfiler(SentryId traceId) async {
142142
try {
143-
return await _channel.invokeMethod('startProfiling', traceId.toString())
143+
return await _channel.invokeMethod('startProfiler', traceId.toString())
144144
as int?;
145145
} catch (error, stackTrace) {
146-
_logError('startProfiling', error, stackTrace);
146+
_logError('startProfiler', error, stackTrace);
147147
return null;
148148
}
149149
}
150150

151+
Future<void> discardProfiler(SentryId traceId) async {
152+
try {
153+
return await _channel.invokeMethod('discardProfiler', traceId.toString());
154+
} catch (error, stackTrace) {
155+
_logError('discardProfiler', error, stackTrace);
156+
}
157+
}
158+
151159
Future<Map<String, dynamic>?> collectProfile(
152-
SentryId traceId, int startTimeNs) async {
160+
SentryId traceId, int startTimeNs, int endTimeNs) async {
153161
try {
154-
return await _channel.invokeMapMethod<String, dynamic>('collectProfile',
155-
{'traceId': traceId.toString(), 'startTime': startTimeNs});
162+
return await _channel.invokeMapMethod<String, dynamic>('collectProfile', {
163+
'traceId': traceId.toString(),
164+
'startTime': startTimeNs,
165+
'endTime': endTimeNs,
166+
});
156167
} catch (error, stackTrace) {
157168
_logError('collectProfile', error, stackTrace);
158169
return null;

flutter/test/mocks.dart

+23-8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ISentrySpan startTransactionShim(
4040
Transport,
4141
// ignore: invalid_use_of_internal_member
4242
SentryTracer,
43+
SentryTransaction,
4344
MethodChannel,
4445
], customMocks: [
4546
MockSpec<Hub>(fallbackGenerators: {#startTransaction: startTransactionShim})
@@ -189,7 +190,8 @@ class TestMockSentryNative implements SentryNative {
189190
var numberOfSetTagCalls = 0;
190191
SentryUser? sentryUser;
191192
var numberOfSetUserCalls = 0;
192-
var numberOfStartProfilingCalls = 0;
193+
var numberOfStartProfilerCalls = 0;
194+
var numberOfDiscardProfilerCalls = 0;
193195
var numberOfCollectProfileCalls = 0;
194196

195197
@override
@@ -270,14 +272,20 @@ class TestMockSentryNative implements SentryNative {
270272

271273
@override
272274
Future<Map<String, dynamic>?> collectProfile(
273-
SentryId traceId, int startTimeNs) {
275+
SentryId traceId, int startTimeNs, int endTimeNs) {
274276
numberOfCollectProfileCalls++;
275277
return Future.value(null);
276278
}
277279

278280
@override
279-
Future<int?> startProfiling(SentryId traceId) {
280-
numberOfStartProfilingCalls++;
281+
Future<int?> startProfiler(SentryId traceId) {
282+
numberOfStartProfilerCalls++;
283+
return Future.value(42);
284+
}
285+
286+
@override
287+
Future<void> discardProfiler(SentryId traceId) {
288+
numberOfDiscardProfilerCalls++;
281289
return Future.value(null);
282290
}
283291
}
@@ -299,7 +307,8 @@ class MockNativeChannel implements SentryNativeChannel {
299307
int numberOfSetContextsCalls = 0;
300308
int numberOfSetExtraCalls = 0;
301309
int numberOfSetTagCalls = 0;
302-
int numberOfStartProfilingCalls = 0;
310+
int numberOfStartProfilerCalls = 0;
311+
int numberOfDiscardProfilerCalls = 0;
303312
int numberOfCollectProfileCalls = 0;
304313

305314
@override
@@ -364,14 +373,20 @@ class MockNativeChannel implements SentryNativeChannel {
364373

365374
@override
366375
Future<Map<String, dynamic>?> collectProfile(
367-
SentryId traceId, int startTimeNs) {
376+
SentryId traceId, int startTimeNs, int endTimeNs) {
368377
numberOfCollectProfileCalls++;
369378
return Future.value(null);
370379
}
371380

372381
@override
373-
Future<int?> startProfiling(SentryId traceId) {
374-
numberOfStartProfilingCalls++;
382+
Future<int?> startProfiler(SentryId traceId) {
383+
numberOfStartProfilerCalls++;
384+
return Future.value(null);
385+
}
386+
387+
@override
388+
Future<int?> discardProfiler(SentryId traceId) {
389+
numberOfDiscardProfilerCalls++;
375390
return Future.value(null);
376391
}
377392
}

0 commit comments

Comments
 (0)