From f172c4de11085065216c98124283effeb0d0f15e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 8 Jul 2024 14:35:00 +0200 Subject: [PATCH] fix: app starts hanging for 30s (#2140) * Update * Update * Add CHANGELOG * Update comment * Update CHANGELOG.md --- CHANGELOG.md | 8 +++++ .../native_app_start_event_processor.dart | 6 ++-- .../native_app_start_integration.dart | 5 ++- .../native_app_start_integration_test.dart | 33 +++++++++++++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d73810fe..a6a26c1553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Fixes + +- App starts hanging for 30s ([#2140](https://github.com/getsentry/sentry-dart/pull/2140)) + - Time out for app start info retrieval has been reduced to 10s + - If `autoAppStarts` is `false` and `setAppStartEnd` has not been called, the app start event processor will now return early instead of waiting for `getAppStartInfo` to finish + ## 8.4.0-beta.1 ### Features diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index 87066aa271..a0da42359e 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -24,16 +24,18 @@ class NativeAppStartEventProcessor implements EventProcessor { return event; } - final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); - + AppStartInfo? appStartInfo; if (!options.autoAppStart) { final appStartEnd = NativeAppStartIntegration.appStartEnd; if (appStartEnd != null) { + appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); appStartInfo?.end = appStartEnd; } else { // If autoAppStart is disabled and appStartEnd is not set, we can't add app starts return event; } + } else { + appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); } final measurement = appStartInfo?.toMeasurement(); diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index c76874d19f..af747dbf36 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -34,7 +34,10 @@ class NativeAppStartIntegration extends Integration { static bool didAddAppStartMeasurement = false; /// Timeout duration to wait for the app start info to be fetched. - static const _timeoutDuration = Duration(seconds: 30); + static const _timeoutDuration = Duration(seconds: 10); + + @visibleForTesting + static Duration get timeoutDuration => _timeoutDuration; /// We filter out App starts more than 60s static const _maxAppStartMillis = 60000; diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index c472b0fa60..707163c790 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -146,6 +146,30 @@ void main() { expect(enriched.spans.isEmpty, true); }); + test( + 'does not trigger timeout if autoAppStart is false and setAppStartEnd is not called', + () async { + // setting a frame callback with a bigger timeout than our app start timeout so the timeout would theoretically be triggered + fixture = Fixture( + frameCallbackTimeout: NativeAppStartIntegration.timeoutDuration + + const Duration(seconds: 5)); + fixture.options.autoAppStart = false; + + await fixture.registerIntegration(); + + final tracer = fixture.createTracer(); + final transaction = SentryTransaction(tracer); + + final processor = fixture.options.eventProcessors.first; + + final stopwatch = Stopwatch()..start(); + await processor.apply(transaction, Hint()) as SentryTransaction; + stopwatch.stop(); + + expect(stopwatch.elapsed < NativeAppStartIntegration.timeoutDuration, + isTrue); + }); + test( 'autoAppStart is false and appStartEnd is set adds app start measurement', () async { @@ -384,9 +408,12 @@ class Fixture extends IntegrationTestFixture { @override MockHub get hub => super.hub as MockHub; - Fixture() - : super((binding) => - NativeAppStartIntegration(binding, FakeFrameCallbackHandler())) { + Fixture({Duration? frameCallbackTimeout}) + : super((binding) => NativeAppStartIntegration( + binding, + FakeFrameCallbackHandler( + finishAfterDuration: frameCallbackTimeout ?? + const Duration(milliseconds: 50)))) { NativeAppStartIntegration.reset(); hub = MockHub(); // ignore: invalid_use_of_internal_member