fix(replay): Associate trace IDs with replay segments#5473
Conversation
When a transaction is captured while replay is recording, the trace ID is now registered with the replay controller and included in the next replay segment. This enables searching for replays by trace ID in the Sentry UI. Fixes #5346 Slack thread: https://sentry.slack.com/archives/CP4UUUF1S/p1779889727948439?thread_ts=1777385469.860819&cid=CP4UUUF1S https://claude.ai/code/session_012wjHQtsEPzcrxSMCufxrDY
1cdc97f to
82b3d84
Compare
📲 Install BuildsAndroid
|
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ad8da22 | 365.86 ms | 427.00 ms | 61.14 ms |
| abfcc92 | 337.38 ms | 427.39 ms | 90.00 ms |
| b8bd880 | 314.56 ms | 336.50 ms | 21.94 ms |
| 44472da | 313.96 ms | 365.35 ms | 51.39 ms |
| b03edbb | 352.20 ms | 423.69 ms | 71.49 ms |
| f6cdbf0 | 314.19 ms | 357.59 ms | 43.40 ms |
| f064536 | 329.00 ms | 395.62 ms | 66.62 ms |
| 806307f | 357.85 ms | 424.64 ms | 66.79 ms |
| d15471f | 343.13 ms | 361.47 ms | 18.34 ms |
| 6edfca2 | 316.43 ms | 398.90 ms | 82.46 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ad8da22 | 1.58 MiB | 2.29 MiB | 719.83 KiB |
| abfcc92 | 1.58 MiB | 2.13 MiB | 557.31 KiB |
| b8bd880 | 1.58 MiB | 2.29 MiB | 722.92 KiB |
| 44472da | 0 B | 0 B | 0 B |
| b03edbb | 1.58 MiB | 2.13 MiB | 557.32 KiB |
| f6cdbf0 | 0 B | 0 B | 0 B |
| f064536 | 1.58 MiB | 2.20 MiB | 633.90 KiB |
| 806307f | 1.58 MiB | 2.10 MiB | 533.42 KiB |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| 6edfca2 | 1.58 MiB | 2.13 MiB | 559.07 KiB |
250a9e4 to
a948a1a
Compare
eda19a1 to
68edd9a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0058908. Configure here.
|
|
||
| protected val currentEvents: Deque<RRWebEvent> = ConcurrentLinkedDeque() | ||
| private val traceIdsLock = Any() | ||
| protected val currentTraceIds: MutableList<String> = mutableListOf() |
There was a problem hiding this comment.
Non-thread-safe list exposed as protected with private lock
Low Severity
currentTraceIds is declared protected (accessible by subclasses) but uses a non-thread-safe mutableListOf(), while its guarding traceIdsLock is private (inaccessible by subclasses). This is inconsistent with the sibling currentEvents, which is also protected but uses a thread-safe ConcurrentLinkedDeque. A subclass accessing currentTraceIds directly would bypass synchronization, risking a data race. Making currentTraceIds private would match the lock's visibility and prevent unsynchronized access.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0058908. Configure here.


📜 Description
This change enables associating trace IDs with replay segments, allowing replays to be searched and filtered by the trace IDs of transactions that occurred during recording.
Key Changes:
registerTraceId()method toReplayControllerinterface and implementationsBaseCaptureStrategyto collect trace IDs in aConcurrentHashMapand include them in generated replay segmentsSentryClient.captureTransaction()to register the transaction's trace ID with the replay controller when a transaction is capturedReplayIntegrationto forward trace ID registration to the active capture strategyReplaySegmentto include trace IDs in the replay payloadImplementation Details:
currentTraceIdsset during a segment's lifetimeSentryId.EMPTY_ID) are filtered out💡 Motivation and Context
This enables better correlation between replays and transactions. When a transaction occurs while replay is recording, its trace ID is now associated with the replay segment, making it possible to:
Closes #5346
💚 How did you test it?
Added comprehensive unit tests covering:
registerTraceIdincludes trace IDs in the next segmentregisterTraceIdclears trace IDs after segment creationregisterTraceIdignores empty trace IDsregisterTraceIddoes nothing when replay is not startedregisterTraceIdforwards to capture strategy when recordingcaptureTransactionregisters trace ID with replay controllerAll tests pass and verify the trace ID registration flow end-to-end.
📝 Checklist
sendDefaultPIIis enabled.https://claude.ai/code/session_012wjHQtsEPzcrxSMCufxrDY