@@ -108,6 +108,10 @@ private enum PreflightStep
108108 private int _suiteT8PollTicks ;
109109 private bool _suiteT8BuildWasRunning ;
110110
111+ // Sentry performance tracing
112+ private ITransactionTracer _sentryTx ;
113+ private ISpan _sentryCurrentSpan ;
114+
111115 // ── Public entry points (called from DataUpdate / DispatchAction) ──────
112116
113117 private void TryStartDataCaptureSuite ( string [ ] skipIds = null )
@@ -184,6 +188,13 @@ private void ProcessDataCaptureSuiteTick()
184188 _suite60HzRecorder = null ;
185189 StopReplayIncidentIndexRecordModeLocked ( "suite_cancel" ) ;
186190 EmitSuiteLifecycleEvent ( "sdk_capture_suite_cancelled" , "Suite cancelled." , "T_cancel" ) ;
191+
192+ // Sentry: finish spans/transaction as cancelled
193+ _sentryCurrentSpan ? . Finish ( SpanStatus . Cancelled ) ;
194+ _sentryCurrentSpan = null ;
195+ _sentryTx ? . Finish ( SpanStatus . Cancelled ) ;
196+ _sentryTx = null ;
197+
187198 _suitePhase = DataCaptureSuitePhase . Cancelled ;
188199 }
189200 return ;
@@ -683,6 +694,12 @@ private void BeginDataCaptureSuite()
683694 _suiteStep = SuiteInternalStep . T0_Rewind ;
684695 _suitePhase = DataCaptureSuitePhase . Running ;
685696
697+ // Sentry performance transaction for the entire suite run
698+ _sentryTx = SentrySdk . StartTransaction ( "data-capture-suite" , "test.run" ) ;
699+ _sentryTx . SetExtra ( "test_run_id" , _suiteTestRunId ) ;
700+ SentrySdk . ConfigureScope ( scope => scope . Transaction = _sentryTx ) ;
701+ _sentryCurrentSpan = _sentryTx . StartChild ( "step" , SuiteInternalStep . T0_Rewind . ToString ( ) ) ;
702+
686703 EmitSuiteLifecycleEvent ( DataCaptureSuiteConstants . EventSuiteStarted ,
687704 $ "Data capture suite started. test_run_id={ _suiteTestRunId } ", "T_start" ) ;
688705 SentrySdk . AddBreadcrumb ( "Data capture suite started" , "lifecycle" ,
@@ -694,6 +711,8 @@ private void BeginDataCaptureSuite()
694711
695712 private void TickSuiteRunning ( )
696713 {
714+ var stepBefore = _suiteStep ;
715+
697716 switch ( _suiteStep )
698717 {
699718 case SuiteInternalStep . T0_Rewind : TickT0_Rewind ( ) ; break ;
@@ -724,6 +743,16 @@ private void TickSuiteRunning()
724743 case SuiteInternalStep . Done : TransitionToLoki ( ) ; break ;
725744 }
726745
746+ // Sentry: finish previous span and start new one when step changes
747+ if ( _suiteStep != stepBefore && _sentryTx != null )
748+ {
749+ _sentryCurrentSpan ? . Finish ( SpanStatus . Ok ) ;
750+ if ( _suiteStep != SuiteInternalStep . Done )
751+ _sentryCurrentSpan = _sentryTx . StartChild ( "step" , _suiteStep . ToString ( ) ) ;
752+ else
753+ _sentryCurrentSpan = null ;
754+ }
755+
727756 // 60Hz recording: every tick while running
728757 _suite60HzRecorder ? . RecordTick ( _irsdk ) ;
729758 }
@@ -1638,6 +1667,12 @@ private void TransitionToLoki()
16381667 _suiteEmitCompleteUtc = DateTime . UtcNow ;
16391668 _suitePhase = DataCaptureSuitePhase . AwaitingLoki ;
16401669
1670+ // Sentry: finish any remaining span and the transaction
1671+ _sentryCurrentSpan ? . Finish ( SpanStatus . Ok ) ;
1672+ _sentryCurrentSpan = null ;
1673+ _sentryTx ? . Finish ( SpanStatus . Ok ) ;
1674+ _sentryTx = null ;
1675+
16411676 var fields = BuildTestFields ( "T_done" ) ;
16421677 fields [ "loki_wait_ms" ] = DataCaptureSuiteConstants . LokiVerifyDelayMs ;
16431678 MergeSessionAndRoutingFields ( fields ) ;
0 commit comments