Skip to content

Commit 0dcea38

Browse files
billyvgclaude
andcommitted
fix(replay): Set replay_id on DSC after buffer-to-session conversion
When `sendBufferedReplayOrFlush` converts from buffer to session mode, it calls `startRecording()` directly but never updates the cached DSC with the new replay_id. The `createDsc` hook only fires for new spans, not for an already-cached DSC on the scope, so the replay_id was missing from all outgoing requests until a new span was created. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4cf5c61 commit 0dcea38

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

packages/replay-internal/src/replay.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ import { getHandleRecordingEmit } from './util/handleRecordingEmit';
5252
import { isExpired } from './util/isExpired';
5353
import { isSessionExpired } from './util/isSessionExpired';
5454
import { debug } from './util/logger';
55-
import { resetReplayIdOnDynamicSamplingContext } from './util/resetReplayIdOnDynamicSamplingContext';
55+
import {
56+
resetReplayIdOnDynamicSamplingContext,
57+
setReplayIdOnDynamicSamplingContext,
58+
} from './util/resetReplayIdOnDynamicSamplingContext';
5659
import { closestElementOfNode } from './util/rrweb';
5760
import { sendReplay } from './util/sendReplay';
5861
import { RateLimitError, ReplayDurationLimitError } from './util/sendReplayRequest';
@@ -619,6 +622,10 @@ export class ReplayContainer implements ReplayContainerInterface {
619622
}
620623

621624
this.startRecording();
625+
626+
if (this.session) {
627+
setReplayIdOnDynamicSamplingContext(this.session.id);
628+
}
622629
}
623630

624631
/**

packages/replay-internal/src/util/resetReplayIdOnDynamicSamplingContext.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,21 @@ export function resetReplayIdOnDynamicSamplingContext(): void {
1818
delete (dsc as Partial<DynamicSamplingContext>).replay_id;
1919
}
2020
}
21+
22+
/**
23+
* Set the `replay_id` field on the cached DSC.
24+
* The cached DSC on the scope (set by browserTracingIntegration) persists across
25+
* session boundaries, and `createDsc` won't fire when a cached DSC already exists.
26+
*/
27+
export function setReplayIdOnDynamicSamplingContext(replayId: string): void {
28+
const dsc = getCurrentScope().getPropagationContext().dsc;
29+
if (dsc) {
30+
dsc.replay_id = replayId;
31+
}
32+
33+
const activeSpan = getActiveSpan();
34+
if (activeSpan) {
35+
const dsc = getDynamicSamplingContextFromSpan(activeSpan);
36+
(dsc as Partial<DynamicSamplingContext>).replay_id = replayId;
37+
}
38+
}

0 commit comments

Comments
 (0)