diff --git a/CHANGELOG.md b/CHANGELOG.md index 4383846760..f15cd25a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Bumped `dio` min verion to `5.2.0` - Log a warning when dropping envelope items ([#3165](https://github.com/getsentry/sentry-dart/pull/3165)) - Call options.log for structured logs ([#3187](https://github.com/getsentry/sentry-dart/pull/3187)) +- Tag all spans during app start with start type info ([#3190](https://github.com/getsentry/sentry-dart/pull/3190)) ### Dependencies diff --git a/packages/flutter/lib/src/integrations/native_app_start_handler.dart b/packages/flutter/lib/src/integrations/native_app_start_handler.dart index b4f9288991..4eda35c0e7 100644 --- a/packages/flutter/lib/src/integrations/native_app_start_handler.dart +++ b/packages/flutter/lib/src/integrations/native_app_start_handler.dart @@ -56,6 +56,7 @@ class NativeAppStartHandler { } else { return; } + sentryTracer.setData("app_start_type", appStartInfo.type.name); // We need to add the measurements before we add the child spans // If the child span finish the transaction will finish and then we cannot add measurements @@ -143,6 +144,7 @@ class NativeAppStartHandler { traceId: transactionTraceId, startTimestamp: appStartInfo.start, endTimestamp: appStartEnd, + appStartType: appStartInfo.type.name, ); await _attachNativeSpans(appStartInfo, transaction, appStartSpan); @@ -155,6 +157,7 @@ class NativeAppStartHandler { traceId: transactionTraceId, startTimestamp: appStartInfo.start, endTimestamp: appStartInfo.pluginRegistration, + appStartType: appStartInfo.type.name, ); final sentrySetupSpan = await _createAndFinishSpan( @@ -165,6 +168,7 @@ class NativeAppStartHandler { traceId: transactionTraceId, startTimestamp: appStartInfo.pluginRegistration, endTimestamp: appStartInfo.sentrySetupStart, + appStartType: appStartInfo.type.name, ); final firstFrameRenderSpan = await _createAndFinishSpan( @@ -175,6 +179,7 @@ class NativeAppStartHandler { traceId: transactionTraceId, startTimestamp: appStartInfo.sentrySetupStart, endTimestamp: appStartEnd, + appStartType: appStartInfo.type.name, ); transaction.children.addAll([ @@ -201,6 +206,7 @@ class NativeAppStartHandler { traceId: transaction.context.traceId, startTimestamp: timeSpan.start, endTimestamp: timeSpan.end, + appStartType: appStartInfo.type.name, ); span.data.putIfAbsent('native', () => true); transaction.children.add(span); @@ -219,6 +225,7 @@ class NativeAppStartHandler { required SentryId traceId, required DateTime startTimestamp, required DateTime endTimestamp, + required String appStartType, }) async { final span = SentrySpan( tracer, @@ -231,6 +238,7 @@ class NativeAppStartHandler { _hub, startTimestamp: startTimestamp, ); + span.setData("app_start_type", appStartType); await span.finish(endTimestamp: endTimestamp); return span; } diff --git a/packages/flutter/test/integrations/native_app_start_handler_test.dart b/packages/flutter/test/integrations/native_app_start_handler_test.dart index a7a5632ad6..e2a953c0a2 100644 --- a/packages/flutter/test/integrations/native_app_start_handler_test.dart +++ b/packages/flutter/test/integrations/native_app_start_handler_test.dart @@ -240,6 +240,13 @@ void main() { expect(fixture.scope.span, isA()); }); + test('added transaction has app_start_type data', () async { + await fixture.call( + appStartEnd: DateTime.fromMillisecondsSinceEpoch(10), + ); + expect(fixture._enrichedTransaction?.data["app_start_type"], 'cold'); + }); + test('added transaction is not bound to scope if already set', () async { final alreadySet = MockSentryTracer(); fixture.scope.span = alreadySet; @@ -404,6 +411,14 @@ void main() { expect(firstFrameRenderSpan, isNotNull); }); + test('have app_start_type data set', () async { + // Verify that app start spans have the app_start_type data set + expect(coldStartSpan?.data["app_start_type"], "cold"); + expect(pluginRegistrationSpan?.data["app_start_type"], "cold"); + expect(sentrySetupSpan?.data["app_start_type"], "cold"); + expect(firstFrameRenderSpan?.data["app_start_type"], "cold"); + }); + test('have correct op', () async { const op = 'app.start.cold'; expect(coldStartSpan?.context.operation, op);