Skip to content

Commit 75a76fc

Browse files
committed
update poc
1 parent 4c976b3 commit 75a76fc

File tree

7 files changed

+402
-114
lines changed

7 files changed

+402
-114
lines changed

flutter/example/lib/auto_close_screen.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class AutoCloseScreenState extends State<AutoCloseScreen> {
2727
description: 'running a $delayInSeconds seconds operation');
2828
await Future.delayed(const Duration(seconds: delayInSeconds));
2929
await childSpan?.finish();
30-
SentryFlutter.reportFullDisplay();
30+
SentryFlutter.reportFullyDisplayed();
3131
// ignore: use_build_context_synchronously
3232
// Navigator.of(context).pop();
3333
}

flutter/example/lib/main.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class _MyAppState extends State<MyApp> {
103103

104104
@override
105105
Widget build(BuildContext context) {
106-
SentryFlutter.reportFullDisplay();
106+
// SentryFlutter.reportFullDisplay();
107107
return feedback.BetterFeedback(
108108
child: ChangeNotifierProvider<ThemeProvider>(
109109
create: (_) => ThemeProvider(),

flutter/lib/src/event_processor/native_app_start_event_processor.dart

+4-22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22

33
import 'package:sentry/sentry.dart';
44

5+
import '../integrations/integrations.dart';
56
import '../native/sentry_native.dart';
67

78
/// EventProcessor that enriches [SentryTransaction] objects with app start
@@ -18,28 +19,9 @@ class NativeAppStartEventProcessor implements EventProcessor {
1819

1920
@override
2021
Future<SentryEvent?> apply(SentryEvent event, {Hint? hint}) async {
21-
final appStartEnd = _native.appStartEnd;
22-
23-
if (appStartEnd != null &&
24-
event is SentryTransaction &&
25-
!_native.didFetchAppStart) {
26-
final nativeAppStart = await _native.fetchNativeAppStart();
27-
if (nativeAppStart == null) {
28-
return event;
29-
}
30-
final measurement = nativeAppStart.toMeasurement(appStartEnd);
31-
// We filter out app start more than 60s.
32-
// This could be due to many different reasons.
33-
// If you do the manual init and init the SDK too late and it does not
34-
// compute the app start end in the very first Screen.
35-
// If the process starts but the App isn't in the foreground.
36-
// If the system forked the process earlier to accelerate the app start.
37-
// And some unknown reasons that could not be reproduced.
38-
// We've seen app starts with hours, days and even months.
39-
if (measurement.value >= _maxAppStartMillis) {
40-
return event;
41-
}
42-
22+
final appStartInfo = AppStartTracker().appStartInfo;
23+
if (appStartInfo != null && event is SentryTransaction) {
24+
final measurement = appStartInfo.measurement;
4325
event.measurements[measurement.name] = measurement;
4426
}
4527
return event;
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/scheduler.dart';
2+
import 'package:meta/meta.dart';
23
import 'package:sentry/sentry.dart';
34

45
import '../../sentry_flutter.dart';
@@ -23,18 +24,14 @@ class NativeAppStartIntegration extends Integration<SentryFlutterOptions> {
2324
'Scheduler binding is null. Can\'t auto detect app start time.');
2425
} else {
2526
schedulerBinding.addPostFrameCallback((timeStamp) async {
27+
final appStartEnd = options.clock();
2628
// ignore: invalid_use_of_internal_member
27-
_native.appStartEnd = options.clock();
29+
_native.appStartEnd = appStartEnd;
2830

29-
final appStartEnd = _native.appStartEnd;
31+
if (!_native.didFetchAppStart) {
32+
final nativeAppStart = await _native.fetchNativeAppStart();
33+
final measurement = nativeAppStart?.toMeasurement(appStartEnd!);
3034

31-
if (_native.appStartEnd != null && !_native!.didFetchAppStart) {
32-
print('fetch app start');
33-
final nativeAppStart = await _native!.fetchNativeAppStart();
34-
if (nativeAppStart == null) {
35-
return;
36-
}
37-
final measurement = nativeAppStart.toMeasurement(appStartEnd!);
3835
// We filter out app start more than 60s.
3936
// This could be due to many different reasons.
4037
// If you do the manual init and init the SDK too late and it does not
@@ -43,49 +40,23 @@ class NativeAppStartIntegration extends Integration<SentryFlutterOptions> {
4340
// If the system forked the process earlier to accelerate the app start.
4441
// And some unknown reasons that could not be reproduced.
4542
// We've seen app starts with hours, days and even months.
46-
if (measurement.value >= 60000) {
43+
if (nativeAppStart == null ||
44+
measurement == null ||
45+
measurement.value >= 60000) {
46+
AppStartTracker().setAppStartInfo(null);
4747
return;
4848
}
4949

50-
final appStartDateTime = DateTime.fromMillisecondsSinceEpoch(
51-
nativeAppStart.appStartTime.toInt());
52-
53-
final transactionContext2 = SentryTransactionContext(
54-
'root ("/")',
55-
'ui.load',
56-
transactionNameSource: SentryTransactionNameSource.component,
57-
// ignore: invalid_use_of_internal_member
58-
origin: SentryTraceOrigins.autoNavigationRouteObserver,
50+
final appStartInfo = AppStartInfo(
51+
DateTime.fromMillisecondsSinceEpoch(
52+
nativeAppStart.appStartTime.toInt()),
53+
appStartEnd,
54+
measurement,
5955
);
6056

61-
final transaction2 = hub.startTransactionWithContext(
62-
transactionContext2,
63-
waitForChildren: true,
64-
autoFinishAfter: Duration(seconds: 3),
65-
trimEnd: true,
66-
startTimestamp: appStartDateTime,
67-
onFinish: (transaction) async {
68-
final nativeFrames = await _native
69-
?.endNativeFramesCollection(transaction.context.traceId);
70-
if (nativeFrames != null) {
71-
final measurements = nativeFrames.toMeasurements();
72-
for (final item in measurements.entries) {
73-
final measurement = item.value;
74-
transaction.setMeasurement(
75-
item.key,
76-
measurement.value,
77-
unit: measurement.unit,
78-
);
79-
}
80-
}
81-
});
82-
83-
final ttidSpan = transaction2.startChild('ui.load.initial_display', startTimestamp: appStartDateTime);
84-
await ttidSpan.finish(endTimestamp: appStartEnd);
85-
86-
SentryNavigatorObserver.ttfdSpan = transaction2.startChild('ui.load.full_display', startTimestamp: appStartDateTime);
87-
88-
print('end of the road');
57+
AppStartTracker().setAppStartInfo(appStartInfo);
58+
} else {
59+
AppStartTracker().setAppStartInfo(null);
8960
}
9061
});
9162
}
@@ -99,3 +70,40 @@ class NativeAppStartIntegration extends Integration<SentryFlutterOptions> {
9970

10071
/// Used to provide scheduler binding at call time.
10172
typedef SchedulerBindingProvider = SchedulerBinding? Function();
73+
74+
@internal
75+
class AppStartInfo {
76+
final DateTime start;
77+
final DateTime end;
78+
final SentryMeasurement measurement;
79+
80+
AppStartInfo(this.start, this.end, this.measurement);
81+
}
82+
83+
@internal
84+
class AppStartTracker {
85+
static final AppStartTracker _instance = AppStartTracker._internal();
86+
87+
factory AppStartTracker() => _instance;
88+
89+
AppStartInfo? _appStartInfo;
90+
91+
AppStartInfo? get appStartInfo => _appStartInfo;
92+
Function(AppStartInfo?)? _callback;
93+
94+
AppStartTracker._internal();
95+
96+
void setAppStartInfo(AppStartInfo? appStartInfo) {
97+
_appStartInfo = appStartInfo;
98+
_notifyObserver();
99+
}
100+
101+
void onAppStartComplete(Function(AppStartInfo?) callback) {
102+
_callback = callback;
103+
_callback?.call(_appStartInfo);
104+
}
105+
106+
void _notifyObserver() {
107+
_callback?.call(_appStartInfo);
108+
}
109+
}

0 commit comments

Comments
 (0)