Skip to content

feat: Span-first trace lifecycle (experimental)#3659

Merged
buenaflor merged 65 commits intomainfrom
feat/span-first
Apr 22, 2026
Merged

feat: Span-first trace lifecycle (experimental)#3659
buenaflor merged 65 commits intomainfrom
feat/span-first

Conversation

@buenaflor
Copy link
Copy Markdown
Contributor

@buenaflor buenaflor commented Apr 22, 2026

Introduces the streaming span-first trace lifecycle, where spans are buffered and transmitted individually as they finish instead of aggregated into a transaction envelope at the root.

Enabled via SentryOptions.traceLifecycle = SentryTraceLifecycle.stream. The API is marked @experimental while it stabilises. Existing SentryTraceLifecycle.static (transaction-based) remains the default.

Integrations that autoinstrument spans (frames tracking, app start, TTID/TTFD, navigation, user interaction, HTTP, databases, GraphQL link) branch on the lifecycle and use the v2 startSpan API in stream mode.

This PR is the aggregation of multiple PRs and should not be reviewed as it is very large

buenaflor and others added 30 commits November 26, 2025 17:27
* Add setAttributeS

* Update

* Update

* Add removeAttribute

* Add scope test

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Merge scope

* Update

* Fix analyzer

* Fix analyzer

* Add Spanv2 protocol

* Add Spanv2 protocol

* Update

* Rename

* Update

* Update

* Update

* Update

* Update

* Analyze

* Consistency

* Update API

* Update API

* Remove debug print

* Fix analyze
* Add setAttributeS

* Update

* Update

* Add removeAttribute

* Add scope test

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Merge scope

* Update

* Fix analyzer

* Fix analyzer

* Add Spanv2 protocol

* Add Spanv2 protocol

* Update

* Rename

* Update

* Update

* Update

* Add support for spans protocol

* Add envelope structure

* Update

* Update

* Remove buffer

* Update

* Update

* Update

* Dedupe item payload creation

* Analze

* Analyze

* Update

* Update
…ffolding (#3377)

* Update

* Updateg

* Update

* Update

* Update

* Remove unnecessary import

* Remove unnecessary import

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Refactor Span implementations to standardize spanId handling and improve attribute management. Added spanId to SimpleSpan and NoOpSpan, and updated UnsetSpan to throw errors for unimplemented methods. Enhanced tests to verify spanId creation.

* Add tests for finished spans as parents and handling of disabled tracing

- Introduced a test to verify that a finished span can be used as a parent for a new span.
- Added a test to ensure that when tracing is disabled, starting a span results in a NoOpSpan and does not affect active spans.

* Implement idempotent behavior for ending spans and enhance tests for span finalization

- Added a check in the `end` method of `SimpleSpan` to prevent multiple calls from altering the end timestamp after the span is finished.
- Introduced a new test to verify that calling `end` on an already finished span does not change its state or timestamp.
- Updated existing tests to use a consistent method for obtaining the hub instance.

* Fix end method in SimpleSpan to ensure captureSpan is called after setting isFinished flag

* Update scope_test to use getActiveSpan method for retrieving the last active span

* Refactor Span documentation and clean up tests

- Removed redundant comment about parent span being null in the Span interface.
- Enhanced documentation for the attributes getter to specify the use of Map.unmodifiable.
- Cleaned up the hub_span_test by removing an incomplete test case regarding finished spans as parents.
- Updated scope_test to include assertions for active spans in the cloned state.

* Update TODO comment for clarity

* Update TODO comment for span processing

* Rename test for setting span status to improve clarity

* Fix end method in SimpleSpan to ensure endTimestamp is set as UTC

- Updated the end method to convert the endTimestamp to UTC correctly.
- Added a test to verify that endTimestamp is set as UTC when the end method is called.

* Update span_test to ensure endTimestamp is set as UTC in tests

- Modified the test to convert the end timestamp to UTC before passing it to the span's end method, ensuring consistency with the expected behavior.
* Update

* Update

* Fix test

* Update

* Update

* Update

* Update

* Add JNI utility tests for Dart to Java object conversion

This commit introduces a new test file for verifying the conversion of Dart objects to JNI types, including primitives, lists, and maps. The tests ensure that null values are dropped appropriately and that nested structures are handled correctly. The tests are designed to run on the Android platform only.

* Rename native FFI JNI utility test file to native JNI utility test for clarity

* Refactor JNI utility tests to improve clarity and consistency

This commit updates the JNI utility tests by renaming assertion functions for better readability and consistency. The changes include replacing direct assertions with dedicated helper functions that check for equality, ensuring null checks are performed, and enhancing the overall structure of the test cases. This refactor aims to improve maintainability and clarity in the test suite.

* Remove null checks from setContexts and setExtra methods in SentryNativeJava class for cleaner code.

* Refactor JNI utility tests to enhance structure and readability

This commit updates the JNI utility tests by restructuring the test cases for better clarity and maintainability. Key changes include the introduction of local variables for input data, improved assertion handling with arena management, and the renaming of helper functions for consistency. These modifications aim to streamline the testing process and ensure accurate validation of Dart to JNI object conversions.

* Enhance JNI utility tests by adding missing line breaks for improved readability

This commit introduces line breaks in the JNI utility test file to enhance the overall readability of the code. The changes aim to improve the visual structure of the test cases, making it easier to follow the logic and organization of the tests.
…s e.g log, span (#3407)

* feat(telemetry): Enhance telemetry processing with buffer registration and mock implementation

- Updated `DefaultTelemetryProcessor` to include a method for registering telemetry buffers.
- Refactored the constructor to accept a logger callback instead of Sentry options.
- Introduced `MockTelemetryBuffer` for testing purposes, allowing simulation of buffer behavior.
- Added comprehensive tests for the `DefaultTelemetryProcessor`, covering initialization, item addition, and buffer flushing.

* refactor(tests): Remove unused initialization tests from telemetry processor tests

- Deleted the initialization test group in `telemetry_processor_test.dart` as the tests were marked with TODOs and not implemented. This cleanup improves the clarity and focus of the test suite.

* feat(telemetry): Integrate telemetry processing into SentryOptions

- Added a `telemetryProcessor` field to `SentryOptions`, initialized with a `NoOpTelemetryProcessor`.
- Enhanced `DefaultTelemetryProcessor` to manage span and log buffers based on Sentry options.
- Implemented methods for adding spans and logs, along with flushing buffers for telemetry data transmission.
- Introduced a `NoOpTelemetryProcessor` for scenarios where telemetry is not enabled.

* refactor(telemetry): Simplify telemetry buffer handling in DefaultTelemetryProcessor

- Removed unnecessary comments regarding buffer creation based on options.
- Updated tests to reflect changes in method names for adding spans and logs.
- Enhanced test coverage for handling cases where buffers may not be registered, ensuring no exceptions are thrown.
- Introduced a test subclass to facilitate mock buffer creation for testing purposes.

* feat(telemetry): Implement in-memory telemetry buffer for span and log processing

- Introduced `InMemoryTelemetryBuffer` class for managing telemetry items with time and size-based flushing.
- Updated `DefaultTelemetryProcessor` to utilize `InMemoryTelemetryBuffer` for span and log buffering.
- Removed obsolete buffer creation methods to streamline buffer initialization.
- Adjusted tests to instantiate `DefaultTelemetryProcessor` directly, enhancing clarity and consistency.

* fix(span): Ensure child span inherits traceId from parent correctly

- Updated the SimpleSpan constructor to inherit traceId from the parent span if available, ensuring consistent trace propagation.
- Removed the condition that set 'is_segment' to true when there is no parent span, simplifying the span representation.
- Added a test to verify that child spans correctly inherit the traceId from their parent, even after resetting the propagation context.

* fix(noop_span): Correct segmentSpan implementation to return the current instance

- Updated the segmentSpan getter in NoOpSpan to return the current instance instead of a new NoOpSpan, ensuring proper span behavior and consistency in span hierarchy.

* Formatting

* feat(telemetry): Enhance DefaultTelemetryProcessor with customizable buffer factories

- Introduced `TelemetryBufferFactory` type for creating telemetry buffers, allowing for custom buffer implementations.
- Updated `DefaultTelemetryProcessor` constructor to accept optional buffer factory parameters for spans and logs, defaulting to `InMemoryTelemetryBuffer`.
- Modified tests to utilize mock buffers, improving test flexibility and clarity in buffer handling.

* refactor(span): Update SimpleSpan to use configurable clock for timestamps

- Changed the initialization of _startTimestamp to use a configurable clock from the Hub options instead of the current UTC time.
- Updated the _endTimestamp assignment to also utilize the Hub's clock, ensuring consistent time handling across spans.

* refactor(telemetry): Simplify DefaultTelemetryProcessor by removing buffer factory parameters

- Removed the optional buffer factory parameters from the DefaultTelemetryProcessor constructor, directly accepting span and log buffers instead.
- Streamlined the addSpan and addLog methods to utilize a common _add method for handling telemetry items.
- Updated tests to reflect changes in the DefaultTelemetryProcessor instantiation, enhancing clarity in buffer management.

* refactor(telemetry): Remove unused telemetry item import from NoOpSpan

- Eliminated the import of `telemetry_item.dart` in `noop_span.dart` as it is no longer needed.
- Streamlined the `NoOpSpan` class to focus on its core functionality without unnecessary dependencies.

* refactor(telemetry): Replace TelemetryItem with SentryEncodable interface

- Updated SentryLog and Span classes to implement the new SentryEncodable interface instead of the deprecated TelemetryItem.
- Refactored TelemetryBuffer and related classes to work with SentryEncodable, enhancing type safety and consistency across telemetry processing.
- Introduced SentryEncodable interface to define a common method for JSON serialization, streamlining the encoding process for telemetry items.

* docs(telemetry): Add documentation for SentryEncodable and TelemetryBuffer

- Introduced a description for the SentryEncodable interface, clarifying its purpose for JSON serialization.
- Added documentation for the TelemetryBuffer class, explaining its functionality in batching telemetry items for efficient transmission to Sentry.

* refactor(span): Improve traceId inheritance logic in SimpleSpan constructor

- Updated the SimpleSpan constructor to conditionally inherit traceId from the parent span only if it is not empty, enhancing trace propagation accuracy.
- Simplified the logic for determining the traceId, ensuring clearer and more reliable span behavior.

* fix(span): Ensure endTimestamp is stored in UTC format in SimpleSpan

- Updated the assignment of _endTimestamp in SimpleSpan to convert endTimestamp to UTC if provided, ensuring consistent timestamp handling across spans.

* feat(telemetry): Prevent NoOpSpan and UnsetSpan from being added to the buffer

- Updated the addSpan method in DefaultTelemetryProcessor to ignore NoOpSpan and UnsetSpan instances, ensuring they are not added to the telemetry buffer.
- Added unit tests to verify that NoOpSpan and UnsetSpan cannot be added to the buffer, enhancing the robustness of span handling.

* docs(telemetry): Enhance documentation for TelemetryProcessor methods

- Added documentation comments for the addSpan, addLog, and flush methods in the TelemetryProcessor interface, clarifying their functionality and usage.
- Improved code readability and maintainability by providing clear descriptions of method behaviors and expected outcomes.

* docs(telemetry): Remove outdated flush method documentation in DefaultTelemetryProcessor

- Deleted the documentation comments for the flush method in DefaultTelemetryProcessor, as they were no longer relevant.
- This change helps maintain clarity and accuracy in the codebase by ensuring that documentation reflects the current implementation.

* docs(telemetry): Remove outdated constructor documentation in DefaultTelemetryProcessor

- Deleted the documentation comment for the constructor in DefaultTelemetryProcessor, as it was no longer relevant.
- This change helps maintain clarity and accuracy in the codebase by ensuring that documentation reflects the current implementation.

* refactor(telemetry): Remove SentryEncodable interface and simplify related classes

- Eliminated the SentryEncodable interface, removing its implementation from SentryLog and Span classes.
- Updated TelemetryBuffer and its subclasses to no longer depend on SentryEncodable, enhancing type flexibility.
- Adjusted related methods to accommodate the removal of the interface, streamlining the telemetry processing codebase.

* refactor(telemetry): Rename BufferedItem to EncodedItem and update related types

- Renamed BufferedItem class to EncodedItem to better reflect its purpose of pairing items with their encoded bytes for size tracking and transmission.
- Updated InMemoryTelemetryBuffer to use an ItemEncoder type instead of a serializer function, enhancing clarity in item encoding.
- Adjusted the add method to utilize the new encoder, streamlining the telemetry processing workflow.

* refactor(span): Simplify traceId assignment in SimpleSpan constructor

- Updated the traceId assignment logic in the SimpleSpan constructor to enhance clarity by removing unnecessary null checks.
- Added an override for the toJson method, ensuring proper JSON serialization of the SimpleSpan instance.

* refactor(telemetry): Integrate telemetry processing into SentryClient

- Added telemetry processing capabilities to SentryClient by introducing DefaultTelemetryProcessor and InMemoryTelemetryBuffer for log and span handling.
- Updated the constructor to initialize the telemetry processor, preparing for future removal of the log batcher.
- Renamed EncodedItem to BufferedItem to better represent its role in telemetry data management.

* refactor(telemetry): Implement JsonEncodable interface for telemetry classes

- Introduced JsonEncodable interface to standardize JSON serialization across telemetry-related classes.
- Updated SentryLog and Span classes to implement the new interface, ensuring consistent toJson method implementation.
- Simplified InMemoryTelemetryBuffer by removing the encoder parameter, directly utilizing the toJson method for item encoding.

* refactor(telemetry): Update telemetry buffer implementation and enhance SentryClient tests

- Removed unused import from sentry_client.dart to clean up the code.
- Updated InMemoryTelemetryBuffer's add method to use a temporary variable for BufferedItem, improving clarity.
- Enhanced SentryClient tests by adding a new group to verify the default telemetry processor initialization, ensuring proper setup during client instantiation.

* refactor(telemetry): Rename flush methods to clear for clarity

- Updated TelemetryBuffer and its implementations to rename the flush method to clear, reflecting its functionality of sending and clearing buffered items.
- Adjusted SentryClient to include a TODO for future telemetry processor integration.
- Enhanced documentation to clarify the purpose of the clear method in telemetry processing.

* refactor(telemetry): Rename flush method to clear in MockTelemetryBuffer

- Updated MockTelemetryBuffer to rename the flush method to clear, aligning with its intended functionality of clearing buffered items.
- Adjusted related test cases to reflect the method name change, ensuring consistency across the telemetry processing tests.

* refactor(telemetry): Update futures type in telemetry processor

- Changed the type of futures in DefaultTelemetryProcessor from Future<void> to Future, allowing for more flexibility in handling future results.
- This adjustment improves the clarity and usability of the telemetry processing logic.

* refactor(telemetry): Rename asyncFlush to asyncClear in MockTelemetryBuffer

- Updated the MockTelemetryBuffer class to rename the asyncFlush parameter to asyncClear, aligning with the method's functionality of clearing items.
- Adjusted related test cases to reflect this change, ensuring consistency in the telemetry processing tests.
* feat(telemetry): Enhance InMemoryTelemetryBuffer with envelope builders and logging

- Introduced `EnvelopeBuilder` interface and implementations for log and span items, facilitating structured telemetry data handling.
- Updated `InMemoryTelemetryBuffer` to utilize envelope builders for encoding and sending telemetry items, improving data transmission efficiency.
- Enhanced logging capabilities within `InMemoryTelemetryBuffer` to capture encoding errors and buffer flushing events.
- Added comprehensive tests for `InMemoryTelemetryBuffer`, ensuring correct behavior for item addition, flushing, and error handling.

* refactor(telemetry): Rename clear method to flush for consistency

- Updated the TelemetryBuffer interface and its implementations to rename the `clear` method to `flush`, aligning with its functionality of sending buffered items.
- Adjusted the InMemoryTelemetryBuffer and DefaultTelemetryProcessor classes to reflect this change, ensuring consistent terminology across the codebase.
- Modified related tests to use the new `flush` method, maintaining test integrity and clarity.

* feat(telemetry): Introduce TelemetryBufferPolicy and enhance InMemoryTelemetryBuffer

- Added a new `TelemetryBufferPolicy` class to define flushing behavior with configurable parameters such as `flushTimeout`, `maxBufferSizeBytes`, and `maxItemCount`.
- Updated `InMemoryTelemetryBuffer` to utilize `TelemetryBufferPolicy`, allowing for more flexible buffer management based on item count and size.
- Enhanced the SentryClient initialization to include a maximum item count for telemetry buffering, improving data handling efficiency.

* feat(telemetry): Integrate TelemetryBufferPolicy into SentryClient initialization

- Updated SentryClient to utilize the new TelemetryBufferPolicy for managing telemetry item count, enhancing buffer management.
- This change improves the efficiency of telemetry data handling by allowing for configurable item limits during client setup.

* fix(telemetry): Correct defaultMaxBufferSizeBytes initialization

- Updated the initialization of defaultMaxBufferSizeBytes in TelemetryBufferPolicy to use a more concise expression, improving code clarity and consistency.

* refactor(telemetry): Simplify InMemoryTelemetryBuffer initialization

- Removed the policy parameter from InMemoryTelemetryBuffer initialization in SentryClient, streamlining the constructor and improving code clarity.
- This change prepares for future enhancements related to telemetry processing.

* refactor(telemetry): Rename TelemetryBufferPolicy to TelemetryBufferConfig

- Renamed the TelemetryBufferPolicy class to TelemetryBufferConfig for improved clarity and consistency in naming.
- Updated references in InMemoryTelemetryBuffer and related tests to reflect the new class name, ensuring seamless integration and functionality.

* refactor(telemetry): Update InMemoryTelemetryBuffer to use TelemetryBufferConfig

- Replaced references to TelemetryBufferPolicy with TelemetryBufferConfig in InMemoryTelemetryBuffer and its tests, ensuring consistent naming and improved clarity.
- Adjusted the constructor and internal logic to utilize the new configuration class for buffer management parameters.

* feat(telemetry): Reject items exceeding max buffer size in InMemoryTelemetryBuffer

- Implemented a check in InMemoryTelemetryBuffer to drop items that exceed the maximum buffer size, preventing oversized items from being added.
- Updated tests to verify that items exceeding the buffer size are correctly rejected and not sent to the transport.
* Refactor telemetry spans to use SentrySpanV2

- Updated span-related classes to implement SentrySpanV2, enhancing the telemetry system's structure and consistency.
- Replaced instances of Span with SentrySpanV2 across Hub, NoOpHub, and related classes to unify span handling.
- Introduced new span types: RecordingSentrySpanV2, NoOpSentrySpanV2, and UnsetSentrySpanV2 for improved span management.
- Removed obsolete span classes and methods, streamlining the codebase and enhancing clarity.
- Updated tests to reflect changes in span handling, ensuring robust coverage for new implementations.

* Remove unnecessary comment from in_memory_telemetry_buffer.dart and update DefaultTelemetryProcessor to remove outdated TODO comment regarding item type.

* Refactor in_memory_telemetry_buffer.dart to enhance error logging and type safety

- Updated OnFlushCallback type parameter from S to T for improved clarity.
- Enhanced error logging to include runtime type information and stack traces for better debugging.
- Simplified item count increment logic for consistency.

* Refactor telemetry buffer classes for improved clarity and functionality

- Changed abstract class declaration to use 'abstract base' for better type safety.
- Updated InMemoryTelemetryBuffer and GroupedInMemoryTelemetryBuffer to use 'final' for class declarations, enhancing immutability.
- Simplified error handling in the onFlush method by using a more generic Future type.
- Improved item storage logic in GroupedInMemoryTelemetryBuffer by utilizing putIfAbsent for clarity.
- Removed unnecessary imports from telemetry_buffer.dart to streamline the codebase.

* Refactor span handling and telemetry logging for improved clarity

- Updated span-related classes to replace 'defaultTraceId' with 'traceId' and 'onSpanEnded' with 'onSpanEnd' for consistency in naming conventions.
- Enhanced logging in RecordingSentrySpanV2 to include warnings for invalid span states, improving error tracking.
- Removed unnecessary imports from sentry_client.dart to streamline the codebase.
- Updated tests to reflect changes in span initialization and logging, ensuring robust coverage for new implementations.

* Enhance span logging for invalid states in Hub class

- Added a warning log for invalid span states in the captureSpan method, improving error tracking and debugging capabilities.
- Removed redundant telemetryProcessor call for NoOpSentrySpanV2, streamlining span handling logic.

* Refactor MutableAttributesMixin declaration for clarity

- Changed the declaration of MutableAttributesMixin from 'abstract mixin class' to 'mixin', enhancing code clarity and consistency in the telemetry attributes implementation.

* Refactor telemetry imports and span handling for improved clarity

- Replaced imports from 'telemetry/telemetry.dart' with 'telemetry/span/sentry_span_v2.dart' across multiple files to streamline the codebase and enhance clarity in span management.
- Updated span-related classes to utilize the new SentrySpanV2 structure, improving consistency in telemetry span handling.
- Removed obsolete 'attributes_mixin.dart' and 'telemetry.dart' files, consolidating span functionality into a more cohesive structure.
- Adjusted tests to reflect changes in span initialization and imports, ensuring robust coverage for new implementations.

* Enhance error logging in InMemoryTelemetryBuffer and streamline span key extraction

- Updated error logging in _BaseInMemoryTelemetryBuffer to include the type parameter T for improved clarity in encoding failures.
- Moved the spanGroupKeyExtractor declaration in DefaultTelemetryProcessorIntegration to a more appropriate location, ensuring better organization and visibility for testing purposes.

* Add spanId initialization to RecordingSentrySpanV2 in tests

- Updated the createSpan method in telemetry_processor_integration_test.dart, telemetry_processor_test.dart, and span_test.dart to include spanId initialization using SpanId.newId().
- This change ensures consistent span identification across test cases, enhancing the reliability of telemetry span handling.

* Update spanGroupKeyExtractor to use segmentSpan for improved span identification

- Modified the spanGroupKeyExtractor in DefaultTelemetryProcessorIntegration to utilize segmentSpan.spanId instead of spanId, enhancing the accuracy of span grouping in telemetry processing.

* Remove test for empty attributes map in span_test.dart to streamline test coverage

* Add spanId initialization in createSpan method for consistent span identification

- Updated the createSpan method in scope_test.dart to include spanId initialization using SpanId.newId(), ensuring uniformity in span identification across tests.

* Refactor telemetry processing classes for improved organization and functionality

- Updated import paths in sentry_options.dart to reflect new structure.
- Introduced new classes for telemetry buffering and processing, including TelemetryBuffer, InMemoryTelemetryBuffer, and DefaultTelemetryProcessor, enhancing the management of telemetry data.
- Added TelemetryBufferConfig for configurable buffer settings.
- Streamlined test imports to align with the new class structure, ensuring consistency across the codebase.

* Refactor _BaseInMemoryTelemetryBuffer for improved organization

- Rearranged member variable declarations in _BaseInMemoryTelemetryBuffer to enhance code readability and maintainability. This change does not affect functionality but improves the overall structure of the class.

* Clarify attributes getter documentation

Updated the documentation for the attributes getter to clarify that it returns a read-only view using Map.unmodifiable and that the map must not be mutated.

* Refactor spanId handling in RecordingSentrySpanV2 and related classes

- Removed spanId parameter from the RecordingSentrySpanV2 constructor, initializing it directly within the class.
- Updated spanGroupKeyExtractor to handle null segmentSpan gracefully.
- Adjusted createSpan methods in tests to reflect the removal of spanId initialization, ensuring consistency across test cases.

* Update segmentSpan assignment in RecordingSentrySpanV2 constructor

- Modified the assignment of _segmentSpan to use parentSpan directly if segmentSpan is null, ensuring more robust handling of parent span relationships.

* Update segmentSpan getter in RecordingSentrySpanV2 for improved null handling

- Changed the segmentSpan getter to return itself when _segmentSpan is null, enhancing the logic for span relationships.
- Updated the corresponding test to reflect this change in behavior, ensuring clarity in expected outcomes.

* Refactor spanGroupKeyExtractor in DefaultTelemetryProcessorIntegration for improved span identification

- Updated the spanGroupKeyExtractor to directly use segmentSpan.spanId, removing the null check for segmentSpan. This change enhances the accuracy of span grouping in telemetry processing.
- Removed outdated comment in RecordingSentrySpanV2 regarding segmentSpan behavior, clarifying the getter's functionality.

* Add DefaultTelemetryProcessorIntegration to Sentry options

- Integrated DefaultTelemetryProcessorIntegration into the Sentry options, enhancing telemetry processing capabilities.
- Updated tests to verify the addition of DefaultTelemetryProcessorIntegration, ensuring it is included in the integration list during initialization.

* Enhance documentation and internal logging

- Introduced detailed logging for buffer operations in _BaseInMemoryTelemetryBuffer, including item encoding and flushing events.
- Updated the DefaultTelemetryProcessor to log when the telemetry processor is already set, preventing redundant assignments.
- Added new callback types for better handling of telemetry item encoding and flushing.
- Refactored the segmentSpan getter in RecordingSentrySpanV2 for clarity and improved documentation on span relationships.
…ng to `startSpan` (#3429)

* feat(span): Enhance span sampling and telemetry context handling

- Introduced sampling decision logic in the Hub class to determine whether spans should be recorded based on a random sampling rate.
- Updated the captureSpan method to return a Future, allowing for asynchronous handling of span captures.
- Enhanced SentryTraceContextHeader to create headers from RecordingSentrySpanV2, improving telemetry context management.
- Added a factory method for creating SentryTraceContextHeader from spans, facilitating better integration with the telemetry system.
- Updated tests to reflect changes in span handling and sampling logic, ensuring robust coverage for new implementations.

* refactor: rename dscFactory to dscCreator and update related implementations

- Renamed the `dscFactory` parameter to `dscCreator` in the Hub and RecordingSentrySpanV2 classes for clarity.
- Updated all references and implementations across the codebase to reflect this change.
- Added a new `captureSpan` method in NoOpSentryClient to support the updated span handling.
- Adjusted tests to accommodate the new parameter name.

* feat: introduce span sampling context and lifecycle management

- Added `SentryTraceLifecycle` enum to control trace data collection methods (streaming vs static).
- Enhanced `SentrySamplingContext` to include span sampling context and lifecycle options.
- Updated `RecordingSentrySpanV2` to support sampling decisions for root and child spans.
- Modified `Hub` class to evaluate sampling decisions at the root span level, ensuring child spans inherit the sampling decision.
- Added tests to verify sampling inheritance and behavior across nested spans.
- Updated example application to utilize the new streaming trace lifecycle option.

* refactor: update span handling and sampling context management

- Refactored `captureSpan` method in `Hub`, `NoOpSentryClient`, and `SentryClient` to return void instead of FutureOr<void> for consistency.
- Enhanced `SentrySamplingContext` with new constructors for transaction and span contexts, improving clarity in sampling decision evaluations.
- Updated `SentryTracesSampler` to utilize the new sampling context structure, ensuring proper handling of static and streaming trace lifecycles.
- Added comments to clarify the limitations of distributed trace support in the current implementation.
- Adjusted tests to validate the new span handling and sampling context behavior, ensuring robust coverage for the updated functionality.

* refactor: enhance SentrySamplingContext with dual-mode support

- Updated `SentrySamplingContext` to clarify its dual-mode functionality for transaction and span contexts, ensuring backwards compatibility.
- Added runtime checks and comments to guide usage in static and streaming modes.
- Included TODOs for future simplification once the legacy transaction API is removed.

* fix: update error types in SentrySamplingContext tests

- Changed expected error types in `SentrySamplingContext` tests from `AssertionError` to `StateError` for accessing `transactionContext` and `spanContext`.
- Improved formatting in test cases for better readability.
- Removed unnecessary blank lines in mock telemetry processor.

* fix: correct sampling decision references in SentryTraceContextHeader

- Updated the `SentryTraceContextHeader` class to use the correct sampling decision properties from the `span` object instead of the `hub.scope.propagationContext`.
- Ensured that `sampleRand` and `sampled` are now accurately derived from the `span.samplingDecision`, improving the integrity of trace context handling.

* fix: update return statements in captureSpan method for consistency

- Modified the `captureSpan` method in the `Hub` class to return void instead of null for better clarity and consistency in handling no-op scenarios.
- Ensured that the return type aligns with the recent refactor of span handling, improving overall code readability.

* fix: update captureSpan method to return void for consistency

- Changed the return type of the `captureSpan` method in `MockSentryClient` from `FutureOr<void>` to `void` to align with recent refactoring efforts.
- This update enhances clarity and consistency in the method's behavior, following similar changes made in the `Hub` class.

* fix: update sampling decision reference in trace context tests

- Modified the test for `SentryTraceContextHeader` to use the sampling decision from the span instead of the propagation context.
- Updated the test case to reflect the new sampling decision structure, ensuring accurate testing of trace context handling.

* refactor: clean up unused imports and methods in trace context and telemetry processor

- Removed unnecessary imports from `SentryTraceContextHeader` to streamline the codebase.
- Eliminated the unused `close` method in `MockTelemetryProcessor`, enhancing code clarity and maintainability.

* Rename DscCreator to DscCreatorCallback

* Document attributes field in SentrySpanSamplingContextV2

Added documentation for the attributes field.

* refactor: simplify span creation in telemetry tests

- Replaced specific span creation methods with a unified `createSpan` method in telemetry tests, enhancing code clarity and reducing redundancy.
- Updated the `Fixture` class to support optional `dscCreator` and `samplingDecision` parameters, streamlining span initialization.

* fix: improve error handling in SentrySamplingContext

- Replaced StateError throws with internalLogger error calls in the transactionContext and spanContext getters to enhance error reporting and maintain backwards compatibility.
- This change provides clearer logging for developers when accessing context in incorrect modes.

* refactor: update SentryTraceContextHeader to accept options and replayId

- Modified the `fromRecordingSpan` factory method in `SentryTraceContextHeader` to accept `SentryOptions` and `replayId` as parameters instead of `Hub`.
- Updated the `dscCreator` in the `Hub` class to reflect these changes, ensuring proper context propagation.
- Adjusted related tests to use the new method signature, enhancing clarity and consistency in span creation.

* refactor: remove redundant StateError tests in SentrySamplingContext

- Eliminated tests that checked for StateError throws when accessing transactionContext and spanContext, as these checks are no longer necessary following recent error handling improvements.
- This cleanup enhances the clarity of the test suite by focusing on relevant functionality and expected behaviors.

* Formaatting
…` and add `traceLifecycle` guards to start APIs (#3435)

* feat(span): Enhance span sampling and telemetry context handling

- Introduced sampling decision logic in the Hub class to determine whether spans should be recorded based on a random sampling rate.
- Updated the captureSpan method to return a Future, allowing for asynchronous handling of span captures.
- Enhanced SentryTraceContextHeader to create headers from RecordingSentrySpanV2, improving telemetry context management.
- Added a factory method for creating SentryTraceContextHeader from spans, facilitating better integration with the telemetry system.
- Updated tests to reflect changes in span handling and sampling logic, ensuring robust coverage for new implementations.

* refactor: rename dscFactory to dscCreator and update related implementations

- Renamed the `dscFactory` parameter to `dscCreator` in the Hub and RecordingSentrySpanV2 classes for clarity.
- Updated all references and implementations across the codebase to reflect this change.
- Added a new `captureSpan` method in NoOpSentryClient to support the updated span handling.
- Adjusted tests to accommodate the new parameter name.

* feat: introduce span sampling context and lifecycle management

- Added `SentryTraceLifecycle` enum to control trace data collection methods (streaming vs static).
- Enhanced `SentrySamplingContext` to include span sampling context and lifecycle options.
- Updated `RecordingSentrySpanV2` to support sampling decisions for root and child spans.
- Modified `Hub` class to evaluate sampling decisions at the root span level, ensuring child spans inherit the sampling decision.
- Added tests to verify sampling inheritance and behavior across nested spans.
- Updated example application to utilize the new streaming trace lifecycle option.

* refactor: update span handling and sampling context management

- Refactored `captureSpan` method in `Hub`, `NoOpSentryClient`, and `SentryClient` to return void instead of FutureOr<void> for consistency.
- Enhanced `SentrySamplingContext` with new constructors for transaction and span contexts, improving clarity in sampling decision evaluations.
- Updated `SentryTracesSampler` to utilize the new sampling context structure, ensuring proper handling of static and streaming trace lifecycles.
- Added comments to clarify the limitations of distributed trace support in the current implementation.
- Adjusted tests to validate the new span handling and sampling context behavior, ensuring robust coverage for the updated functionality.

* refactor: enhance SentrySamplingContext with dual-mode support

- Updated `SentrySamplingContext` to clarify its dual-mode functionality for transaction and span contexts, ensuring backwards compatibility.
- Added runtime checks and comments to guide usage in static and streaming modes.
- Included TODOs for future simplification once the legacy transaction API is removed.

* fix: update error types in SentrySamplingContext tests

- Changed expected error types in `SentrySamplingContext` tests from `AssertionError` to `StateError` for accessing `transactionContext` and `spanContext`.
- Improved formatting in test cases for better readability.
- Removed unnecessary blank lines in mock telemetry processor.

* fix: correct sampling decision references in SentryTraceContextHeader

- Updated the `SentryTraceContextHeader` class to use the correct sampling decision properties from the `span` object instead of the `hub.scope.propagationContext`.
- Ensured that `sampleRand` and `sampled` are now accurately derived from the `span.samplingDecision`, improving the integrity of trace context handling.

* fix: update return statements in captureSpan method for consistency

- Modified the `captureSpan` method in the `Hub` class to return void instead of null for better clarity and consistency in handling no-op scenarios.
- Ensured that the return type aligns with the recent refactor of span handling, improving overall code readability.

* fix: update captureSpan method to return void for consistency

- Changed the return type of the `captureSpan` method in `MockSentryClient` from `FutureOr<void>` to `void` to align with recent refactoring efforts.
- This update enhances clarity and consistency in the method's behavior, following similar changes made in the `Hub` class.

* fix: update sampling decision reference in trace context tests

- Modified the test for `SentryTraceContextHeader` to use the sampling decision from the span instead of the propagation context.
- Updated the test case to reflect the new sampling decision structure, ensuring accurate testing of trace context handling.

* refactor: clean up unused imports and methods in trace context and telemetry processor

- Removed unnecessary imports from `SentryTraceContextHeader` to streamline the codebase.
- Eliminated the unused `close` method in `MockTelemetryProcessor`, enhancing code clarity and maintainability.

* refactor: replace log batcher with telemetry processor and update related tests and imports

* add trace lifecycle guards and tests for static and streaming modes

* Rename DscCreator to DscCreatorCallback

* Document attributes field in SentrySpanSamplingContextV2

Added documentation for the attributes field.

* refactor: simplify span creation in telemetry tests

- Replaced specific span creation methods with a unified `createSpan` method in telemetry tests, enhancing code clarity and reducing redundancy.
- Updated the `Fixture` class to support optional `dscCreator` and `samplingDecision` parameters, streamlining span initialization.

* fix: improve error handling in SentrySamplingContext

- Replaced StateError throws with internalLogger error calls in the transactionContext and spanContext getters to enhance error reporting and maintain backwards compatibility.
- This change provides clearer logging for developers when accessing context in incorrect modes.

* refactor: update SentryTraceContextHeader to accept options and replayId

- Modified the `fromRecordingSpan` factory method in `SentryTraceContextHeader` to accept `SentryOptions` and `replayId` as parameters instead of `Hub`.
- Updated the `dscCreator` in the `Hub` class to reflect these changes, ensuring proper context propagation.
- Adjusted related tests to use the new method signature, enhancing clarity and consistency in span creation.

* refactor: remove redundant StateError tests in SentrySamplingContext

- Eliminated tests that checked for StateError throws when accessing transactionContext and spanContext, as these checks are no longer necessary following recent error handling improvements.
- This cleanup enhances the clarity of the test suite by focusing on relevant functionality and expected behaviors.

* Formaatting

* add mock telemetry processor implementation for testing telemetry integration

* Formaatting

* Formatting

* fix: update span lifecycle tests to remove warning logs in streaming mode

* fix: update trace lifecycle warnings and start span handling for static mode
* feat: introduce span capture pipeline and semantic attributes for telemetry

- Added `SpanCapturePipeline` to manage span capturing and attribute enrichment.
- Introduced `SemanticAttributesConstants` for standardized telemetry attributes.
- Updated `SentryClient` to utilize the new span capture pipeline.
- Enhanced lifecycle hooks to support processing spans with additional attributes.
- Added utility extensions for managing span attributes and default attributes.
- Implemented tests for the new span capture functionality and attribute handling.

* refactor: remove unused SpanAttributeUtils extension

- Deleted the SpanAttributeUtils extension as it is no longer needed following recent changes to the span capture pipeline and attribute management.

* feat: add SpanAttributeUtils extension for SentrySpanV2

- Introduced a new extension `SpanAttributeUtils` to enhance `SentrySpanV2` by adding a method to conditionally add attributes if they are absent.
- Removed the unused import of `span_attribute_utils.dart` from `span_capture_pipeline.dart`.
- Created a new mock class `FakeSpanCapturePipeline` for testing purposes, which captures spans and scopes during tests.

* feat: enhance load contexts integration tests with trace lifecycle scenarios

- Added tests to verify the addition of native attributes to spans when using the streaming trace lifecycle.
- Implemented a test to ensure no callbacks are registered with the static trace lifecycle.
- Updated the device context in the test fixture to include brand, model, and family attributes, along with OS version.

* Fix tests

* Fix tests

* Fix tests

* Refine captureSpan warning and update TODO comments

Updated warning message for static trace lifecycle and removed ignored span from TODO.

* Review

* Fix nullable

* Fix compilation

* Fix compilation

* Fix compilation
Combines span-first feature with main branch changes:
- Merged telemetry processor support for spans, logs, and metrics
- Combined envelope/envelope item factories for all telemetry types
- Unified SentryClient capture pipelines
- Added metric lifecycle callbacks to LoadContextsIntegration
- Retained span processing callbacks for streaming trace lifecycle

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
buenaflor and others added 13 commits April 7, 2026 16:16
…comments

Keep deprecated attributes as primary constants with TODO comments pointing
to their stable replacements. Remove stable replacement constants that were
added prematurely — they will be introduced when the migration happens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce the foundational pieces needed to project Sentry Contexts onto
span, log, and metric attribute maps for the telemetry enrichment pipeline:

- Extend SemanticAttributesConstants with stable app, user.geo, os, culture,
  device, and http keys aligned with Sentry Conventions / OTel semantic
  conventions.
- Add internal toAttributes() projections to SentryApp, SentryCulture,
  SentryDevice, SentryOperatingSystem, SentryRuntime, and SentryUser that
  emit the subset of fields with a defined stable key.
- Add EnricherEventProcessor.buildContexts() with io/web implementations so
  telemetry callbacks can obtain a fresh, platform-derived Contexts instance
  independent of the event apply() flow.

No behavior change for events: event.contexts is still populated via the
existing apply() field merges. toAttributes() is intended for span v2
attributes; event payloads continue to use toJson.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Settle on the shorter .stream identifier for the streaming span-first
trace lifecycle. Mechanical rename across the Dart core, Flutter, and
integration packages (dio, drift, file, hive, isar, link, sqflite,
supabase).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contexts.toAttributes previously took runtimes.first for process.runtime.*
attributes. When both Dart and Flutter runtimes are present (as in Flutter
builds), list order is not guaranteed, so the Flutter runtime could win and
mask the Dart VM version.

Look up the Dart runtime by name and emit flutter.version and flutter.channel
as separate attributes sourced from the compile-time Flutter defines. This
mirrors the OpenTelemetry process.runtime.* semantics (Dart VM) while keeping
Flutter framework metadata as its own dimension.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Route platform-derived context attributes (device, os) through the
enricher integration pipelines instead of a cached defaultAttributes
singleton and ad-hoc native attribute builders:

- Drop _operatingSystem.toAttributes() from defaultAttributes; sdk,
  environment, release, and user attributes stay there.
- Introduce EnricherIntegration which registers lifecycle callbacks that
  attach minimal device/os attributes to logs, metrics, and non-segment
  spans, and the full Contexts.toAttributes() projection to segment spans.
- Rename minimalDeviceAttributes to minimalContextAttributes and expand it
  with os keys so logs, metrics, and non-segment spans receive OS from the
  enricher path instead of defaultAttributes.
- Refactor LoadContextsIntegration to obtain native contexts once and
  filter via the shared minimalContextAttributes set, splitting cached
  session attributes from fresh per-segment attributes. Drops the bespoke
  os.*/device.* attribute builder.

Enricher is now the single source of device and os attributes across logs,
metrics, and spans; defaultAttributes covers SDK metadata, env/release,
and user only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rt spans

Set app.vitals.ttid.value, app.vitals.ttfd.value, and
app.vitals.start.{cold,warm}.value millisecond durations on their
respective spans using the semantic attribute constants. Closes the
"add mobile vitals specific attributes later" TODO in
NativeAppStartHandlerV2.

Also tightens reportFullyDisplayed to read the span once and compute
the end timestamp alongside the attribute for consistency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The streaming trace lifecycle is still stabilising. Annotate
SentryOptions.traceLifecycle with @experimental so external consumers
see a dartanalyzer warning when they set it.

Add experimental_member_use to the per-file ignore lists of the SDK's
own call sites (integrations, navigation, sampling, and their tests),
since the warning is meant for users of the API, not the internal
implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EnricherEventProcessor previously carried a buildContexts() method that
ignored events entirely and existed only so the telemetry lifecycle
callbacks could piggyback on its io/web conditional-import polymorphism.
The method broke the processor's single responsibility and confused
readers.

Extract platform detection into a dedicated PlatformContextProvider with
io/web implementations under lib/src/platform/. The enricher event
processor now delegates detection to the provider and keeps only the
event-merge semantics (preserving user-supplied context fields). The
enricher integration takes the provider directly, and Sentry.init
constructs one provider and shares it with both so caching state is not
duplicated.

Consolidate the shared "filter minimal attributes from Contexts" pattern
(which the load contexts integration also duplicated) into a
Contexts.toMinimalAttributes() extension next to minimalContextAttributes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per the span filtering spec, the SDK must emit a client report outcome
with the ignored or sample_rate discard reason and span category for
every span the SDK declines to send.

- startSpan now records one (ignored, span, 1) outcome on every
  ignoreSpans rule match, and one (sample_rate, span, 1) outcome at
  each rejection point in the sampling/parent chain.
- startIdleSpan is covered by the shared _sampleForRootSpan path.

Also fix a latent bug in the ignore cascade: when an ignoreSpans rule
matched a segment (root), attempted children were being promoted to
new root segments because resolvedParentSpan ended up null. Per the
filtering spec, a root match must cascade the ignore to all descendants;
only a child match may re-parent. Branch on
parent.recordingParent == null && parent.isIgnored to distinguish the
two cases, cascade NoOpSentrySpanV2.instance for segment ignores, and
keep the existing re-parent behavior for child ignores. Each attempted
descendant under an ignored segment now correctly produces its own
ignored outcome.

Removes two TODO(next-pr) markers that tracked these.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…art spans

Add the SemanticAttributesConstants.appVitalsStartValue constant
('app.vitals.start.value') as the forward-compatible unified key for
app start duration, with the cold/warm distinction carried by the
already-existing appVitalsStartType.

NativeAppStartHandlerV2 now emits three attributes on the app start
span:

- The legacy appVitalsStart{Cold,Warm}Value (kept for consumers during
  the deprecation window).
- The new unified appVitalsStartValue (same millisecond duration).
- appVitalsStartType ('cold' or 'warm').

Both the legacy and unified value keys carry the same SentryAttribute
instance, so consumers reading either attribute see consistent data.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… to .stream

Completes the rename in the example app that was missed when the
enum value was renamed across the rest of the monorepo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a TODO note on FlutterEnricherEventProcessor to track porting its
Flutter-specific context enrichment (app.in_foreground, os.theme,
culture.is_24_hour_format, widget locale, flutter_context, etc.) onto
the span v2 attribute path via a FlutterPlatformContextProvider. Marked
low priority since LoadContextsIntegration already covers most fields
on native platforms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • packages/flutter/lib/src/integrations/native_app_start_integration.dart

@buenaflor buenaflor changed the title feat: Span-first trace lifecycle (span v2) feat: Span-first trace lifecycle (experimental) Apr 22, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

❌ Patch coverage is 82.67544% with 237 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.76%. Comparing base (d5a1225) to head (7680b78).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../tracing/instrumentation/instrumentation_span.dart 0.00% 82 Missing ⚠️
.../lib/src/tracing/instrumentation/span_factory.dart 23.52% 13 Missing ⚠️
packages/dart/lib/src/hub_adapter.dart 0.00% 12 Missing ⚠️
...src/integrations/native_app_start_integration.dart 0.00% 11 Missing ⚠️
packages/dart/lib/src/hub.dart 91.93% 10 Missing ⚠️
packages/dart/lib/src/protocol/sentry_app.dart 50.00% 10 Missing ⚠️
...dart/lib/src/protocol/sentry_operating_system.dart 56.52% 10 Missing ⚠️
.../telemetry/span/idle_recording_sentry_span_v2.dart 88.23% 10 Missing ⚠️
packages/dart/lib/src/noop_hub.dart 0.00% 8 Missing ⚠️
...event_processor/enricher/enricher_integration.dart 86.36% 6 Missing ⚠️
... and 25 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3659      +/-   ##
==========================================
- Coverage   86.98%   86.76%   -0.22%     
==========================================
  Files         321      335      +14     
  Lines       10802    11919    +1117     
==========================================
+ Hits         9396    10342     +946     
- Misses       1406     1577     +171     
Flag Coverage Δ
sentry 86.63% <79.47%> (-1.25%) ⬇️
sentry_dio 97.73% <100.00%> (ø)
sentry_drift 93.57% <ø> (ø)
sentry_file 65.29% <100.00%> (+1.76%) ⬆️
sentry_firebase_remote_config 100.00% <ø> (ø)
sentry_flutter 91.13% <91.51%> (-0.26%) ⬇️
sentry_hive 77.48% <100.00%> (+4.96%) ⬆️
sentry_isar 74.37% <ø> (+0.71%) ⬆️
sentry_link 21.50% <62.50%> (+17.55%) ⬆️
sentry_logging 97.01% <ø> (ø)
sentry_sqflite 88.81% <100.00%> (+0.41%) ⬆️
sentry_supabase 97.27% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

Android Performance metrics 🚀

  Plain With Sentry Diff
Startup time 436.25 ms 439.20 ms 2.95 ms
Size 14.31 MiB 15.56 MiB 1.25 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
192b44c 472.26 ms 477.34 ms 5.08 ms
6b69699 456.06 ms 557.44 ms 101.38 ms
d5a1225 377.37 ms 366.56 ms -10.81 ms
a10aff4 488.19 ms 515.02 ms 26.83 ms
40c8f93 417.10 ms 482.60 ms 65.50 ms
e3f3ea1 420.16 ms 436.54 ms 16.39 ms
67de70c 375.88 ms 356.11 ms -19.77 ms
426fbfd 368.10 ms 353.23 ms -14.87 ms
bbdbcb9 400.81 ms 409.12 ms 8.31 ms
40751bf 421.09 ms 424.82 ms 3.73 ms

App size

Revision Plain With Sentry Diff
192b44c 13.93 MiB 14.93 MiB 1.00 MiB
6b69699 6.54 MiB 7.70 MiB 1.17 MiB
d5a1225 14.31 MiB 15.49 MiB 1.19 MiB
a10aff4 13.93 MiB 15.06 MiB 1.13 MiB
40c8f93 13.93 MiB 15.00 MiB 1.06 MiB
e3f3ea1 13.93 MiB 15.18 MiB 1.25 MiB
67de70c 14.31 MiB 15.49 MiB 1.19 MiB
426fbfd 13.93 MiB 15.06 MiB 1.13 MiB
bbdbcb9 13.93 MiB 15.18 MiB 1.25 MiB
40751bf 14.31 MiB 15.49 MiB 1.19 MiB

Previous results on branch: feat/span-first

Startup times

Revision Plain With Sentry Diff
16c8a82 401.38 ms 415.22 ms 13.84 ms
de96551 399.14 ms 438.14 ms 39.00 ms
bb21a6f 395.93 ms 406.68 ms 10.75 ms
d6f9f12 382.65 ms 379.29 ms -3.36 ms
b6831cb 391.60 ms 376.32 ms -15.28 ms
b04fa89 371.83 ms 375.35 ms 3.51 ms
254bfb0 405.62 ms 419.40 ms 13.78 ms
8c1c46a 381.02 ms 384.47 ms 3.45 ms
471badc 363.45 ms 360.00 ms -3.45 ms
02dd58d 368.38 ms 366.25 ms -2.13 ms

App size

Revision Plain With Sentry Diff
16c8a82 13.93 MiB 15.18 MiB 1.25 MiB
de96551 13.93 MiB 15.18 MiB 1.25 MiB
bb21a6f 13.93 MiB 15.18 MiB 1.25 MiB
d6f9f12 13.93 MiB 15.18 MiB 1.25 MiB
b6831cb 14.09 MiB 15.28 MiB 1.19 MiB
b04fa89 14.31 MiB 15.56 MiB 1.25 MiB
254bfb0 14.30 MiB 15.55 MiB 1.25 MiB
8c1c46a 14.30 MiB 15.55 MiB 1.25 MiB
471badc 13.93 MiB 15.18 MiB 1.25 MiB
02dd58d 14.09 MiB 15.28 MiB 1.19 MiB

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 22, 2026

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
sentry_flutter_example io.sentry.flutter.sample 9.18.0 (1) Release

⚙️ sentry-flutter Build Distribution Settings

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

iOS Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1259.75 ms 1260.85 ms 1.10 ms
Size 5.73 MiB 6.18 MiB 463.85 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4298701 1243.56 ms 1262.29 ms 18.72 ms
e1ab497 1260.92 ms 1260.22 ms -0.69 ms
6f47800 1247.52 ms 1259.37 ms 11.85 ms
ea06d23 1254.02 ms 1252.60 ms -1.42 ms
5f4cc67 1236.77 ms 1237.94 ms 1.17 ms
7cfee3b 1260.90 ms 1273.14 ms 12.24 ms
1777727 1249.21 ms 1258.40 ms 9.18 ms
cfca825 1244.71 ms 1249.96 ms 5.24 ms
bfabaf2 1251.72 ms 1253.38 ms 1.67 ms
38a22c2 1257.60 ms 1259.71 ms 2.12 ms

App size

Revision Plain With Sentry Diff
4298701 20.70 MiB 22.46 MiB 1.76 MiB
e1ab497 5.53 MiB 6.01 MiB 487.96 KiB
6f47800 7.86 MiB 9.44 MiB 1.58 MiB
ea06d23 5.53 MiB 5.96 MiB 443.26 KiB
5f4cc67 5.73 MiB 6.17 MiB 455.49 KiB
7cfee3b 20.70 MiB 22.46 MiB 1.75 MiB
1777727 5.73 MiB 6.17 MiB 453.78 KiB
cfca825 5.66 MiB 6.10 MiB 453.28 KiB
bfabaf2 5.53 MiB 6.01 MiB 487.95 KiB
38a22c2 5.73 MiB 6.17 MiB 453.62 KiB

Previous results on branch: feat/span-first

Startup times

Revision Plain With Sentry Diff
b6831cb 1257.18 ms 1248.54 ms -8.64 ms
fd7a63c 1260.69 ms 1256.58 ms -4.10 ms
62e8c63 1259.91 ms 1266.23 ms 6.32 ms
2537512 1264.26 ms 1273.12 ms 8.87 ms
5e69f20 1267.37 ms 1265.06 ms -2.31 ms
755404b 1248.94 ms 1257.37 ms 8.43 ms
1cbd3cd 1254.33 ms 1243.46 ms -10.87 ms
8c1c46a 1256.83 ms 1261.56 ms 4.73 ms
cba88c6 1273.63 ms 1265.92 ms -7.71 ms
a4f736f 1263.78 ms 1260.63 ms -3.14 ms

App size

Revision Plain With Sentry Diff
b6831cb 5.66 MiB 6.10 MiB 453.17 KiB
fd7a63c 5.53 MiB 6.02 MiB 501.30 KiB
62e8c63 5.66 MiB 6.09 MiB 450.13 KiB
2537512 5.66 MiB 6.10 MiB 453.18 KiB
5e69f20 5.53 MiB 5.97 MiB 448.19 KiB
755404b 5.53 MiB 5.97 MiB 448.18 KiB
1cbd3cd 5.66 MiB 6.10 MiB 453.19 KiB
8c1c46a 5.73 MiB 6.17 MiB 453.41 KiB
cba88c6 5.53 MiB 5.97 MiB 447.31 KiB
a4f736f 5.53 MiB 5.97 MiB 448.11 KiB

@buenaflor buenaflor marked this pull request as ready for review April 22, 2026 11:44
Copilot AI review requested due to automatic review settings April 22, 2026 11:44
@buenaflor buenaflor merged commit 8af916c into main Apr 22, 2026
143 of 148 checks passed
@buenaflor buenaflor deleted the feat/span-first branch April 22, 2026 11:44
}

_options.lifecycleRegistry.dispatchCallback(OnSpanStartV2(span));
_idleSpan = span;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The _idleSpan field on the Hub is not cleared when an idle span ends, causing the ended span object to be retained in memory unnecessarily.
Severity: LOW

Suggested Fix

The _idleSpan field on the Hub should be set to null when the span ends. This can be done within the captureSpan() method by adding a check for when an IdleRecordingSentrySpanV2 instance has ended and then clearing the _idleSpan reference.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/dart/lib/src/hub.dart#L944

Potential issue: When an `IdleRecordingSentrySpanV2` finishes naturally via its timer,
the reference to it in the `Hub`'s `_idleSpan` field is not cleared. While the
`_currentIdleSpan` getter correctly prevents exposing the ended span, the object itself
is retained in memory. This unnecessary memory retention persists until the next idle
span is started, which overwrites the reference, or until `Hub.close()` is called. This
constitutes a minor memory leak, bounded to a single span object per `Hub`.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an experimental “span-first” streaming trace lifecycle (SentryOptions.traceLifecycle = SentryTraceLifecycle.stream) so spans are buffered/captured individually as they finish (SpanV2), while keeping the existing transaction-based lifecycle as default.

Changes:

  • Add SpanV2 capture/processing pipeline (buffers, envelopes, lifecycle hooks, options) and new traceLifecycle switch.
  • Update multiple integrations (Flutter + package integrations like Dio/File/DB/GraphQL) to branch behavior based on lifecycle and use the SpanV2 APIs in streaming mode.
  • Add extensive integration/unit tests plus a new internal _sentry_testing package to share test utilities.

Reviewed changes

Copilot reviewed 153 out of 153 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/supabase/pubspec.yaml Add internal test utilities dependency
packages/supabase/lib/src/sentry_supabase_tracing_client.dart Update span factory call signature
packages/sqflite/pubspec.yaml Add internal test utilities dependency
packages/sqflite/lib/src/sentry_sqflite_database_factory.dart Guard span creation on parent
packages/sqflite/lib/src/sentry_sqflite.dart Guard span creation on parent
packages/sqflite/lib/src/sentry_database.dart Guard span creation on parent
packages/sqflite/lib/src/sentry_batch.dart Guard span creation on parent
packages/link/pubspec.yaml Add internal test utilities dependency
packages/link/lib/src/sentry_tracing_link.dart Branch root span by lifecycle
packages/link/lib/src/sentry_response_parser.dart Guard span creation on parent
packages/link/lib/src/sentry_request_serializer.dart Guard span creation on parent
packages/isar/test/spanv2_integration_test.dart Add SpanV2 integration tests
packages/isar/pubspec.yaml Add internal test utilities dependency
packages/isar/lib/src/sentry_span_helper.dart Guard span creation on parent
packages/hive/test/spanv2_integration_test.dart Add SpanV2 integration tests
packages/hive/pubspec.yaml Add internal test utilities dependency
packages/hive/lib/src/sentry_span_helper.dart Guard span creation on parent
packages/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart Add streaming interaction tests
packages/flutter/test/navigation/sentry_navigator_observer_test.dart Add streaming TTD tests + fake tracker
packages/flutter/test/navigation/sentry_display_widget_test.dart Enable TTFD tracing in fixture
packages/flutter/test/navigation/sentry_display_test.dart Split tests by lifecycle + V2 tracker
packages/flutter/test/navigation/fake_time_to_display_tracker_v2.dart Add fake TimeToDisplayTrackerV2
packages/flutter/test/mocks.dart Add span collection to telemetry mock
packages/flutter/test/integrations/native_app_start_integration_test.dart Add V2 native app start handler test stub
packages/flutter/test/integrations/generic_app_start_integration_test.dart Add streaming generic app start tests
packages/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart Stream-mode idle span interactions
packages/flutter/lib/src/sentry_flutter_options.dart Add timeToDisplayTrackerV2
packages/flutter/lib/src/sentry_flutter.dart Wire V2 native app start + display selection
packages/flutter/lib/src/navigation/sentry_navigator_observer.dart Branch TTD instrumentation by lifecycle
packages/flutter/lib/src/navigation/sentry_display.dart Report fully displayed via V1/V2 tracker
packages/flutter/lib/src/integrations/native_app_start_integration.dart Branch native app start by lifecycle
packages/flutter/lib/src/integrations/native_app_start_handler_v2.dart Implement V2 native app start spans
packages/flutter/lib/src/integrations/native_app_start_handler.dart Refactor parsing into shared helper
packages/flutter/lib/src/integrations/native_app_start_data.dart Shared native app start parsing/types
packages/flutter/lib/src/integrations/load_contexts_integration.dart Add span context enrichment callback
packages/flutter/lib/src/integrations/generic_app_start_integration.dart Stream-mode app-start tracking
packages/flutter/lib/src/integrations/frames_tracking_integration.dart Rework frames tracking for SpanV2
packages/flutter/lib/src/frames_tracking/span_frame_metrics_collector.dart Collector updated for both span types
packages/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart Note future spanv2 port
packages/file/test/spanv2_integration_test.dart Add SpanV2 integration tests
packages/file/pubspec.yaml Add internal test utilities dependency
packages/file/lib/src/sentry_file.dart Guard span creation on parent
packages/drift/test/sentry_drift_test.dart Update test span factory signature
packages/drift/pubspec.yaml Add internal test utilities dependency
packages/drift/lib/src/sentry_span_helper.dart Update span factory call signature
packages/dio/test/spanv2_integration_test.dart Add SpanV2 integration tests
packages/dio/pubspec.yaml Add internal test utilities dependency
packages/dio/lib/src/tracing_client_adapter.dart Guard span creation on parent
packages/dio/lib/src/sentry_transformer.dart Guard span creation on parent
packages/dart/test/telemetry/span/ignore_span_rule_test.dart Add IgnoreSpanRule tests
packages/dart/test/telemetry/processing/processor_test.dart Add span buffer tests
packages/dart/test/telemetry/processing/processor_integration_test.dart Add span buffer integration tests
packages/dart/test/telemetry/processing/buffer_test.dart Add grouped buffer tests
packages/dart/test/sentry_trace_context_header_test.dart Add RecordingSpan DSC tests
packages/dart/test/sentry_sampling_context_test.dart Add SpanV2 sampling context tests
packages/dart/test/sentry_envelope_test.dart Add spans envelope tests
packages/dart/test/sentry_envelope_item_test.dart Add spans envelope item tests
packages/dart/test/sentry_client_test.dart Add captureSpan pipeline test
packages/dart/test/sentry_client_lifecycle_test.dart Verify OnProcessSpan + processor wiring
packages/dart/test/scope_test.dart Add active span tests
packages/dart/test/protocol/sentry_user_test.dart Add user toAttributes tests
packages/dart/test/protocol/sentry_runtime_test.dart Add runtime toAttributes tests
packages/dart/test/protocol/sentry_device_test.dart Add device toAttributes tests
packages/dart/test/protocol/culture_test.dart Add culture toAttributes tests
packages/dart/test/protocol/contexts_test.dart Add contexts toAttributes aggregation tests
packages/dart/test/platform/web_platform_context_provider_test.dart Add web platform contexts tests
packages/dart/test/platform/io_platform_context_provider_test.dart Add IO platform contexts tests
packages/dart/test/mocks/mock_telemetry_processor.dart Capture spans in mock processor
packages/dart/test/mocks/mock_span_capture_pipeline.dart Add fake span capture pipeline
packages/dart/test/mocks/mock_sentry_client.dart Add captureSpan recording
packages/dart/test/mocks/mock_hub.dart Add captureSpan recording
packages/dart/test/hub_test.dart Add lifecycle guards tests
packages/dart/test/event_processor/enricher/web_enricher_test.dart Update for async enricher + provider
packages/dart/test/event_processor/enricher/io_enricher_test.dart Update for provider-based enricher
packages/dart/pubspec.yaml Add internal test utilities dependency
packages/dart/lib/src/utils.dart Add SpanV2 attribute helper extension
packages/dart/lib/src/tracing/instrumentation/span_factory_integration.dart Configure legacy vs streaming spanFactory
packages/dart/lib/src/tracing/instrumentation/span_factory.dart Add streaming span factory implementation
packages/dart/lib/src/tracing/instrumentation/instrumentation_span.dart Add streaming span wrapper + helpers
packages/dart/lib/src/telemetry/telemetry.dart Export SpanV2 APIs
packages/dart/lib/src/telemetry/span/unset_sentry_span_v2.dart Add unset marker span
packages/dart/lib/src/telemetry/span/span_capture_pipeline.dart Implement span capture pipeline
packages/dart/lib/src/telemetry/span/sentry_span_v2.dart Add SpanV2 API surface
packages/dart/lib/src/telemetry/span/sentry_span_status_v2.dart Add SpanV2 status enum
packages/dart/lib/src/telemetry/span/sentry_span_sampling_context.dart Add sampling context for spans
packages/dart/lib/src/telemetry/span/noop_sentry_span_v2.dart Add NoOp SpanV2
packages/dart/lib/src/telemetry/span/ignore_span_rule.dart Add ignore span rules
packages/dart/lib/src/telemetry/sentry_trace_lifecycle.dart Add trace lifecycle enum
packages/dart/lib/src/telemetry/processing/processor_integration.dart Add grouped span buffer integration
packages/dart/lib/src/telemetry/processing/processor.dart Add span buffering to processor
packages/dart/lib/src/telemetry/processing/in_memory_buffer.dart Add grouped in-memory buffer
packages/dart/lib/src/telemetry/default_attributes.dart Add minimal context attrs + projections
packages/dart/lib/src/sentry_traces_sampler.dart Guard sampling logic by lifecycle
packages/dart/lib/src/sentry_tracer.dart Add ignore_for_file annotation
packages/dart/lib/src/sentry_trace_origins.dart Add GraphQL/UI interaction origins
packages/dart/lib/src/sentry_trace_context_header.dart Add fromRecordingSpan factory
packages/dart/lib/src/sentry_sampling_context.dart Add SpanV2 sampling context support
packages/dart/lib/src/sentry_options.dart Add traceLifecycle/ignoreSpans/beforeSendSpan
packages/dart/lib/src/sentry_item_type.dart Add span item type
packages/dart/lib/src/sentry_envelope_item.dart Add span envelope item factory
packages/dart/lib/src/sentry_envelope.dart Add spans envelope factory
packages/dart/lib/src/sentry_client.dart Add captureSpan support
packages/dart/lib/src/sdk_lifecycle_hooks.dart Add OnSpanStartV2/OnProcessSpan events
packages/dart/lib/src/scope.dart Add active span tracking
packages/dart/lib/src/protocol/sentry_user.dart Add toAttributes projection
packages/dart/lib/src/protocol/sentry_span.dart Add finish concurrency guard
packages/dart/lib/src/protocol/sentry_runtime.dart Add toAttributes projection
packages/dart/lib/src/protocol/sentry_operating_system.dart Add toAttributes projection
packages/dart/lib/src/protocol/sentry_geo.dart Add subregion/subdivision fields
packages/dart/lib/src/protocol/sentry_device.dart Add toAttributes projection
packages/dart/lib/src/protocol/sentry_culture.dart Add toAttributes projection
packages/dart/lib/src/protocol/sentry_app.dart Add toAttributes projection
packages/dart/lib/src/protocol/contexts.dart Add contexts toAttributes projection
packages/dart/lib/src/platform/web_platform_context_provider.dart Add web platform contexts provider
packages/dart/lib/src/platform/platform_context_provider.dart Add provider interface + conditional impl
packages/dart/lib/src/platform/io_platform_context_provider.dart Add IO platform contexts provider
packages/dart/lib/src/noop_sentry_client.dart Add captureSpan no-op
packages/dart/lib/src/noop_hub.dart Add SpanV2 hub no-op APIs
packages/dart/lib/src/hub_adapter.dart Forward SpanV2 hub APIs
packages/dart/lib/src/http_client/tracing_client.dart Guard span creation on parent
packages/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart Convert to provider-based async merge
packages/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart Convert to provider-based async merge
packages/dart/lib/src/event_processor/enricher/enricher_integration.dart New integration wiring contexts to signals
packages/dart/lib/src/event_processor/enricher/enricher_event_processor.dart Require provider for enricher factory
packages/dart/lib/sentry.dart Export trace lifecycle + SpanV2
packages/_sentry_testing/pubspec.yaml New internal testing package
packages/_sentry_testing/lib/src/fake_telemetry_processor.dart Fake processor capturing spans for tests
packages/_sentry_testing/lib/_sentry_testing.dart Export test utilities
packages/_sentry_testing/README.md Document internal testing utilities
CHANGELOG.md Note experimental span streaming API

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +95 to +99
final results = <FutureOr<void>>[
spanBuffer?.flush(),
logBuffer?.flush(),
metricBuffer?.flush(),
];
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flush() builds a List<FutureOr<void>> but adds the results of spanBuffer?.flush() / logBuffer?.flush() / metricBuffer?.flush(), which are nullable when the buffer is null. With null-safety this should be a type error. Change results to hold nullable entries (e.g. List<FutureOr<void>?>) or build the list without nulls before calling whereType<Future>().

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +27
switch (span) {
case UnsetSentrySpanV2():
internalLogger.warning(
'captureSpan: span is in an invalid state $UnsetSentrySpanV2.',
);
case NoOpSentrySpanV2():
return;
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switch (span) has a case UnsetSentrySpanV2() that only logs a warning but does not terminate the case (no return/break/continue). Dart switch cases cannot fall through, so this should not compile. Add an explicit return (or combine the patterns into one case) after logging for UnsetSentrySpanV2.

Copilot uses AI. Check for mistakes.
Comment on lines +67 to +86
switch (options.traceLifecycle) {
case SentryTraceLifecycle.stream:
await _nativeAppStartHandlerV2.call(
hub,
options,
appStartEnd: appStartEnd,
);
case SentryTraceLifecycle.static:
if (context == null) {
options.log(SentryLevel.warning,
'Skipping native app start integration because context is null');
return;
}
await _nativeAppStartHandler.call(
hub,
options,
context: context,
appStartEnd: appStartEnd,
);
}
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switch (options.traceLifecycle) inside timingsCallback is missing a terminating statement (break/return) at the end of the stream case. This should either be a compile error (no fallthrough) or unintentionally execute the static case after the v2 handler. Add break/return for each case (or rewrite as if/else).

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +107
switch (options.traceLifecycle) {
case SentryTraceLifecycle.stream:
_onSpanStartStreamCallback = (event) {
final wrapped = StreamingInstrumentationSpan(event.span);
collector.startTracking(wrapped);
};
options.lifecycleRegistry
.registerCallback<OnSpanStartV2>(_onSpanStartStreamCallback!);

_onProcessSpanStreamCallback = (event) {
final wrapped = StreamingInstrumentationSpan(event.span);
if (event.span.endTimestamp != null) {
collector.finishTracking(wrapped, event.span.endTimestamp!);
} else {
options.log(SentryLevel.warning,
'OnProcessSpan fired but span has no endTimestamp');
collector.removeFromActiveSpans(wrapped);
}
};
options.lifecycleRegistry
.registerCallback<OnProcessSpan>(_onProcessSpanStreamCallback!);

case SentryTraceLifecycle.static:
_onSpanStartStaticCallback = (event) {
final wrapped = LegacyInstrumentationSpan(event.span);
collector.startTracking(wrapped);
};
options.lifecycleRegistry
.registerCallback<OnSpanStart>(_onSpanStartStaticCallback!);

_onSpanFinishStaticCallback = (event) {
final wrapped = LegacyInstrumentationSpan(event.span);
if (event.span.endTimestamp != null) {
collector.finishTracking(wrapped, event.span.endTimestamp!);
} else {
options.log(SentryLevel.warning,
'OnSpanFinish fired but span has no endTimestamp');
collector.removeFromActiveSpans(wrapped);
}
};
options.lifecycleRegistry
.registerCallback<OnSpanFinish>(_onSpanFinishStaticCallback!);
}
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switch (options.traceLifecycle) used to register lifecycle callbacks has no terminating break/return at the end of the stream case, so it will either fail to compile (no fallthrough) or accidentally also register the static callbacks. Add explicit termination for each case (or use separate if branches).

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +28
operation: 'serialize.http.client',
description: 'GraphGL request serialization',
)
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the span description: "GraphGL" should be "GraphQL" to match the library/protocol name.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7680b78. Configure here.

SentrySpanV2? parentSpan = const UnsetSentrySpanV2(),
}) =>
_hub.startInactiveSpan(name,
attributes: attributes, parentSpan: parentSpan);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @experimental annotation on startInactiveSpan

Medium Severity

Sentry.startSpan and Sentry.startSpanSync are both annotated with @experimental, but Sentry.startInactiveSpan — part of the same experimental span-streaming API — is missing this annotation. The PR description states "The API is marked @experimental while it stabilises," so this looks like an oversight. Flagged because the project rules require public API stability to be maintained or properly marked.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot (Root)

Reviewed by Cursor Bugbot for commit 7680b78. Configure here.

}
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant attribute-if-absent methods on spans

Low Severity

The extension method addAttributesIfAbsent on SentrySpanV2 (in utils.dart) and the instance method setAttributesIfAbsent on RecordingSentrySpanV2 implement identical logic — adding attributes only when the key is absent. Both are actively used in production code (span_capture_pipeline.dart uses the extension, enricher_integration.dart uses the instance method). This duplication increases maintenance burden and risks inconsistent fixes.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7680b78. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants