Skip to content

feat(replay): Add traces_by_timestamp to replay event#18048

Open
billyvg wants to merge 7 commits intodevelopfrom
billy/replay-802-replay-sdk-needs-to-send-timestamps-w-trace-ids
Open

feat(replay): Add traces_by_timestamp to replay event#18048
billyvg wants to merge 7 commits intodevelopfrom
billy/replay-802-replay-sdk-needs-to-send-timestamps-w-trace-ids

Conversation

@billyvg
Copy link
Member

@billyvg billyvg commented Oct 28, 2025

In order to support moving our custom rrweb events to EAP, we need to send timestamps w/ trace ids so that we can identify which trace the event belongs to.

In order to avoid breaking changes, we should not change the current type of trace_ids field in the replay event, instead we add a new field traces_by_timestamp w/ type [transaction.start_timestamp, traceId][].

Previously, we would clear all trace ids after each replay segment. so if there is not a new transaction, segments would not have a trace id associated at all. I've changed this so that we always keep the most recent trace id in between segments.

Also previously, in order to associate a replay with a trace, we wait until after a type: transaction event is sent successfully. it's possible that the replay integration is loaded after this event is sent and never gets associated with any trace ids. in this case, I've changed it so that we take the trace id from current scope and propagation context, and I use -1 for the timestamp here, but could also change to use current ts.

Closes #19201 (added automatically)

@linear
Copy link

linear bot commented Oct 28, 2025

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.43 kB - -
@sentry/browser - with treeshaking flags 23.9 kB - -
@sentry/browser (incl. Tracing) 42.27 kB - -
@sentry/browser (incl. Tracing, Profiling) 46.92 kB - -
@sentry/browser (incl. Tracing, Replay) 81 kB +0.11% +88 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.58 kB +0.09% +60 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 85.68 kB +0.1% +78 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 97.87 kB +0.08% +77 B 🔺
@sentry/browser (incl. Feedback) 42.15 kB - -
@sentry/browser (incl. sendFeedback) 30.11 kB - -
@sentry/browser (incl. FeedbackAsync) 35.13 kB - -
@sentry/browser (incl. Metrics) 26.54 kB - -
@sentry/browser (incl. Logs) 26.69 kB - -
@sentry/browser (incl. Metrics & Logs) 27.36 kB - -
@sentry/react 27.14 kB - -
@sentry/react (incl. Tracing) 44.52 kB - -
@sentry/vue 29.87 kB - -
@sentry/vue (incl. Tracing) 44.09 kB - -
@sentry/svelte 25.44 kB - -
CDN Bundle 27.97 kB - -
CDN Bundle (incl. Tracing) 43.04 kB - -
CDN Bundle (incl. Logs, Metrics) 28.82 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 43.87 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 67.83 kB +0.12% +75 B 🔺
CDN Bundle (incl. Tracing, Replay) 79.87 kB +0.09% +70 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 80.73 kB +0.08% +61 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 85.3 kB +0.08% +67 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.2 kB +0.08% +64 B 🔺
CDN Bundle - uncompressed 81.83 kB - -
CDN Bundle (incl. Tracing) - uncompressed 127.54 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 84.66 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 130.37 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 208.33 kB +0.14% +288 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 244.43 kB +0.12% +288 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 247.25 kB +0.12% +288 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 257.23 kB +0.12% +288 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 260.04 kB +0.12% +288 B 🔺
@sentry/nextjs (client) 46.87 kB - -
@sentry/sveltekit (client) 42.66 kB - -
@sentry/node-core 52.18 kB +0.01% +1 B 🔺
@sentry/node 166.3 kB - -
@sentry/node - without tracing 93.97 kB - -
@sentry/aws-serverless 109.48 kB - -

View base workflow run

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 8,682 - 9,547 -9%
GET With Sentry 1,647 19% 1,751 -6%
GET With Sentry (error only) 6,021 69% 6,252 -4%
POST Baseline 1,195 - 1,210 -1%
POST With Sentry 574 48% 611 -6%
POST With Sentry (error only) 1,038 87% 1,062 -2%
MYSQL Baseline 3,191 - 3,338 -4%
MYSQL With Sentry 440 14% 526 -16%
MYSQL With Sentry (error only) 2,594 81% 2,731 -5%

View base workflow run

@billyvg
Copy link
Member Author

billyvg commented Oct 28, 2025

@sentry review

@billyvg
Copy link
Member Author

billyvg commented Oct 29, 2025

@sentry review

@billyvg billyvg marked this pull request as ready for review October 29, 2025 22:24
@billyvg billyvg requested a review from a team as a code owner October 29, 2025 22:24
@billyvg billyvg requested a review from chargome October 29, 2025 22:24
if (event.contexts?.trace?.trace_id && replayContext.traceIds.size < 100) {
replayContext.traceIds.add(event.contexts.trace.trace_id);
if (event.contexts?.trace?.trace_id && event.start_timestamp && replayContext.traceIds.length < 100) {
replayContext.traceIds.push([event.start_timestamp, event.contexts.trace.trace_id]);
Copy link

Choose a reason for hiding this comment

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

Bug: Timestamp Handling Ignores Valid Zero Value

The event.start_timestamp check in handleTransactionEvent uses a truthy evaluation, which causes trace IDs to not be recorded for transactions with a start_timestamp of 0. Although rare, 0 is a valid Unix epoch timestamp.

Fix in Cursor Fix in Web

initialUrl: this._context.initialUrl,
errorIds: Array.from(this._context.errorIds),
traceIds: Array.from(this._context.traceIds),
traceIds: this._context.traceIds,
Copy link

Choose a reason for hiding this comment

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

Bug: Shared array reference corrupts replay context

In _popEventContext(), the traceIds array is assigned by reference without creating a copy. When _clearContext() is subsequently called, it only creates a new array via slice(-1) if the length is greater than 1. For arrays with length 0 or 1, both the returned context and this._context share the same array reference. This means subsequent modifications to this._context.traceIds will affect the already-returned event context, potentially corrupting replay event data. The fix should copy the array: traceIds: [...this._context.traceIds] or traceIds: this._context.traceIds.slice().

Fix in Cursor Fix in Web

if (this._context.traceIds.length === 0) {
const currentTraceId = getCurrentScope().getPropagationContext().traceId;
if (currentTraceId) {
this._context.traceIds.push([-1, currentTraceId]);
Copy link
Member

Choose a reason for hiding this comment

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

Could we put a comment in here explaining the -1 ?

In order to support moving our custom rrweb events to EAP, we need to send timestamps w/ trace ids so that we can identify which trace the event belongs to.

In order to avoid breaking changes, we should not change the current type of trace_ids field in the replay event, instead we add a new field traces_by_timestamp
@billyvg billyvg force-pushed the billy/replay-802-replay-sdk-needs-to-send-timestamps-w-trace-ids branch from 1985467 to 84b12da Compare February 5, 2026 21:38
@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

Codecov Results 📊


Generated by Codecov Action

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.

feat(replay): Add traces_by_timestamp to replay event

2 participants