feat: Span-first trace lifecycle (experimental)#3659
Conversation
* 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.
…3391) Co-authored-by: GitHub <noreply@github.com>
* 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>
… logic for better concurrency handling
…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>
🚨 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:
|
Codecov Report❌ Patch coverage is 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Android Performance metrics 🚀
|
| 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 |
📲 Install BuildsAndroid
|
iOS Performance metrics 🚀
|
| 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 |
| } | ||
|
|
||
| _options.lifecycleRegistry.dispatchCallback(OnSpanStartV2(span)); | ||
| _idleSpan = span; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
traceLifecycleswitch. - 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_testingpackage 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.
| final results = <FutureOr<void>>[ | ||
| spanBuffer?.flush(), | ||
| logBuffer?.flush(), | ||
| metricBuffer?.flush(), | ||
| ]; |
There was a problem hiding this comment.
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>().
| switch (span) { | ||
| case UnsetSentrySpanV2(): | ||
| internalLogger.warning( | ||
| 'captureSpan: span is in an invalid state $UnsetSentrySpanV2.', | ||
| ); | ||
| case NoOpSentrySpanV2(): | ||
| return; |
There was a problem hiding this comment.
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.
| 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, | ||
| ); | ||
| } |
There was a problem hiding this comment.
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).
| 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!); | ||
| } |
There was a problem hiding this comment.
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).
| operation: 'serialize.http.client', | ||
| description: 'GraphGL request serialization', | ||
| ) |
There was a problem hiding this comment.
Typo in the span description: "GraphGL" should be "GraphQL" to match the library/protocol name.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ 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); |
There was a problem hiding this comment.
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)
Triggered by project rule: PR Review Guidelines for Cursor Bot (Root)
Reviewed by Cursor Bugbot for commit 7680b78. Configure here.
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
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)
Reviewed by Cursor Bugbot for commit 7680b78. Configure here.


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@experimentalwhile it stabilises. ExistingSentryTraceLifecycle.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
startSpanAPI in stream mode.This PR is the aggregation of multiple PRs and should not be reviewed as it is very large