-
-
Notifications
You must be signed in to change notification settings - Fork 284
feat(span-first): Port native app start integration to V2 span API #3534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 38 commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
e7d39c8
feat(flutter): Add TimeToDisplayTrackerV2 for streaming TTID/TTFD
buenaflor ab04b07
refactor(flutter): Wire TimeToDisplayTrackerV2 through the system
buenaflor f3b0bcb
refactor(flutter): Improve TimeToDisplayTrackerV2 wiring and add stre…
buenaflor 44dcb96
Update logger and example
buenaflor c0f9d6d
Review
buenaflor 14d6df2
Review
buenaflor 9d03dee
Review
buenaflor 4d81a0f
Fix test
buenaflor 027b043
Review
buenaflor fcaa139
Merge branch 'feat/span-first' into feat/span/ttid-ttfd
buenaflor 414f04c
Update
buenaflor 4a8b74b
Update
buenaflor 7768434
review
buenaflor 478f9ec
review
buenaflor 24f154a
feat(tracing): Port native app start integration to V2 span API
buenaflor fe07028
Update
buenaflor 431c3e1
Merge branch 'feat/span/ttid-ttfd' into feat/span/native-app-start-v2
buenaflor 0f29921
feat(tracing): Early idle span creation for native app start parenting
buenaflor 1f99f25
Merge branch 'feat/span-first' of github.com:getsentry/sentry-dart in…
buenaflor 1d8cf1e
Update
buenaflor df04c88
test(flutter): Update TimeToDisplayTrackerV2 tests for new API
buenaflor be373fe
Update
buenaflor 4e72478
feat(flutter): Refine native app start integration and clean up tests
buenaflor 3314ac6
Update
buenaflor 1c04eeb
ref(flutter): Clean up NativeAppStartHandlerV2
buenaflor 271ed31
test(flutter): Remove redundant TimeToDisplayTrackerV2 tests
buenaflor fa63805
ref(flutter): Use fake tracker in navigator observer streaming tests
buenaflor d38be48
Update
buenaflor 312d972
ref(flutter): Enhance error logging in native app start data and refi…
buenaflor 352ebfd
Formatting
buenaflor b62b133
fix: Address review feedback for native app start v2
buenaflor 7ccb5f7
fix: Apply dart format to handler files
buenaflor 353a081
fix: Cancel prepared root navigation on early return and use exhausti…
buenaflor 1365f84
fix: Normalize startTimestamp to UTC in span constructor
buenaflor 96dfe1f
test(dart): assert UTC-normalized start timestamps
buenaflor 07e2909
Test
buenaflor 4cbf46b
chore: Remove unused devtools_options.yaml files from drift and link …
buenaflor 0466ec7
test(flutter): expect UTC-normalized app start span timestamps
buenaflor 339c70d
test(flutter): clean up comments in integration tests
buenaflor 99403b2
refactor(flutter): consolidate attributes for span tracking in Native…
buenaflor 02a9bf3
fix(flutter): handle null context in native app start integration
buenaflor 8c844d1
Cleanup tracker in handler
buenaflor d11c441
refactor(flutter): rename tracking methods for clarity and consistency
buenaflor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
packages/flutter/lib/src/integrations/native_app_start_data.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| // ignore_for_file: invalid_use_of_internal_member | ||
|
|
||
| import 'package:meta/meta.dart'; | ||
|
|
||
| import '../../sentry_flutter.dart'; | ||
| import '../native/native_app_start.dart'; | ||
| import '../utils/internal_logger.dart'; | ||
|
|
||
| /// We filter out App starts more than 60s | ||
| @internal | ||
| const maxAppStartMillis = 60000; | ||
|
|
||
| @internal | ||
| enum AppStartType { cold, warm } | ||
|
|
||
| @internal | ||
| class AppStartInfo { | ||
| AppStartInfo( | ||
| this.type, { | ||
| required this.start, | ||
| required this.end, | ||
| required this.pluginRegistration, | ||
| required this.sentrySetupStart, | ||
| required this.nativeSpanTimes, | ||
| }); | ||
|
|
||
| final AppStartType type; | ||
| final DateTime start; | ||
| final DateTime end; | ||
| final List<TimeSpan> nativeSpanTimes; | ||
|
|
||
| final DateTime pluginRegistration; | ||
| final DateTime sentrySetupStart; | ||
|
|
||
| Duration get duration => end.difference(start); | ||
|
|
||
| SentryMeasurement toMeasurement() { | ||
| final duration = this.duration; | ||
| return type == AppStartType.cold | ||
| ? SentryMeasurement.coldAppStart(duration) | ||
| : SentryMeasurement.warmAppStart(duration); | ||
| } | ||
|
|
||
| String get appStartTypeOperation => 'app.start.${type.name}'; | ||
|
|
||
| String get appStartTypeDescription => | ||
| type == AppStartType.cold ? 'Cold Start' : 'Warm Start'; | ||
| final pluginRegistrationDescription = 'App start to plugin registration'; | ||
| final sentrySetupDescription = 'Before Sentry Init Setup'; | ||
| final firstFrameRenderDescription = 'First frame render'; | ||
| } | ||
|
|
||
| @internal | ||
| class TimeSpan { | ||
| TimeSpan({required this.start, required this.end, required this.description}); | ||
|
|
||
| final DateTime start; | ||
| final DateTime end; | ||
| final String description; | ||
| } | ||
|
|
||
| /// Parses and validates native app start data. | ||
| /// | ||
| /// Returns `null` if validation fails (e.g. >60s duration, missing setup time). | ||
| @internal | ||
| AppStartInfo? parseNativeAppStart( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pull out the common things we can to share logic with native app start handler v2 and v1 |
||
| NativeAppStart nativeAppStart, | ||
| DateTime appStartEnd, | ||
| ) { | ||
buenaflor marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| final sentrySetupStartDateTime = SentryFlutter.sentrySetupStartTime; | ||
| if (sentrySetupStartDateTime == null) { | ||
| return null; | ||
| } | ||
|
|
||
| final appStartDateTime = | ||
| DateTime.fromMillisecondsSinceEpoch(nativeAppStart.appStartTime); | ||
| final pluginRegistrationDateTime = DateTime.fromMillisecondsSinceEpoch( | ||
| nativeAppStart.pluginRegistrationTime); | ||
|
|
||
| final duration = appStartEnd.difference(appStartDateTime); | ||
|
|
||
| // We filter out app start more than 60s. | ||
| // This could be due to many different reasons. | ||
| // If you do the manual init and init the SDK too late and it does not | ||
| // compute the app start end in the very first Screen. | ||
| // If the process starts but the App isn't in the foreground. | ||
| // If the system forked the process earlier to accelerate the app start. | ||
| // And some unknown reasons that could not be reproduced. | ||
| // We've seen app starts with hours, days and even months. | ||
| if (duration.inMilliseconds > maxAppStartMillis) { | ||
| return null; | ||
| } | ||
|
|
||
| List<TimeSpan> nativeSpanTimes = []; | ||
| for (final entry in nativeAppStart.nativeSpanTimes.entries) { | ||
| try { | ||
| final startTimestampMs = entry.value['startTimestampMsSinceEpoch'] as int; | ||
| final endTimestampMs = entry.value['stopTimestampMsSinceEpoch'] as int; | ||
| nativeSpanTimes.add(TimeSpan( | ||
| start: DateTime.fromMillisecondsSinceEpoch(startTimestampMs), | ||
| end: DateTime.fromMillisecondsSinceEpoch(endTimestampMs), | ||
| description: entry.key as String, | ||
| )); | ||
| } catch (e) { | ||
| internalLogger.warning('Failed to parse native span times: $e'); | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| // We want to sort because the native spans are not guaranteed to be in order. | ||
| // Performance wise this won't affect us since the native span amount is very low. | ||
| nativeSpanTimes.sort((a, b) => a.start.compareTo(b.start)); | ||
|
|
||
| return AppStartInfo( | ||
| nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, | ||
| start: appStartDateTime, | ||
| end: appStartEnd, | ||
| pluginRegistration: pluginRegistrationDateTime, | ||
| sentrySetupStart: sentrySetupStartDateTime, | ||
| nativeSpanTimes: nativeSpanTimes, | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.