Skip to content

Commit bdb78f2

Browse files
committed
Merge branch 'develop' into feat-replay-change-sampling-logic
2 parents cff6f95 + 0161cdd commit bdb78f2

File tree

2 files changed

+108
-12
lines changed

2 files changed

+108
-12
lines changed

packages/replay/src/replay.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -392,23 +392,25 @@ export class ReplayContainer implements ReplayContainerInterface {
392392
// than the session replay.
393393
await this.flushImmediate();
394394

395-
if (!continueRecording) {
395+
const hasStoppedRecording = this.stopRecording();
396+
397+
if (!continueRecording || !hasStoppedRecording) {
396398
return;
397399
}
398400

399-
// Stop and re-start recording, but in "session" recording mode
400-
if (this.stopRecording()) {
401-
// Reset all "capture on error" configuration before
402-
// starting a new recording
403-
this.recordingMode = 'session';
401+
// Re-start recording, but in "session" recording mode
404402

405-
// Once this session ends, we do not want to refresh it
406-
if (this.session) {
407-
this.session.shouldRefresh = false;
408-
this._maybeSaveSession();
409-
}
410-
this.startRecording();
403+
// Reset all "capture on error" configuration before
404+
// starting a new recording
405+
this.recordingMode = 'session';
406+
407+
// Once this session ends, we do not want to refresh it
408+
if (this.session) {
409+
this.session.shouldRefresh = false;
410+
this._maybeSaveSession();
411411
}
412+
413+
this.startRecording();
412414
}
413415

414416
/**

packages/replay/test/integration/errorSampleRate.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,100 @@ describe('Integration | errorSampleRate', () => {
158158
});
159159
});
160160

161+
it('manually flushes replay and does not continue to record', async () => {
162+
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 };
163+
mockRecord._emitter(TEST_EVENT);
164+
165+
expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled();
166+
expect(replay).not.toHaveLastSentReplay();
167+
168+
// Does not capture on mouse click
169+
domHandler({
170+
name: 'click',
171+
});
172+
jest.runAllTimers();
173+
await new Promise(process.nextTick);
174+
expect(replay).not.toHaveLastSentReplay();
175+
176+
replay.sendBufferedReplayOrFlush({ continueRecording: false });
177+
178+
await new Promise(process.nextTick);
179+
jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY);
180+
await new Promise(process.nextTick);
181+
182+
expect(replay).toHaveSentReplay({
183+
recordingPayloadHeader: { segment_id: 0 },
184+
replayEventPayload: expect.objectContaining({
185+
replay_type: 'error',
186+
contexts: {
187+
replay: {
188+
error_sample_rate: 1,
189+
session_sample_rate: 0,
190+
},
191+
},
192+
}),
193+
recordingData: JSON.stringify([
194+
{ data: { isCheckout: true }, timestamp: BASE_TIMESTAMP, type: 2 },
195+
TEST_EVENT,
196+
{
197+
type: 5,
198+
timestamp: BASE_TIMESTAMP,
199+
data: {
200+
tag: 'breadcrumb',
201+
payload: {
202+
timestamp: BASE_TIMESTAMP / 1000,
203+
type: 'default',
204+
category: 'ui.click',
205+
message: '<unknown>',
206+
data: {},
207+
},
208+
},
209+
},
210+
]),
211+
});
212+
213+
jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY);
214+
// Check that click will not get captured
215+
domHandler({
216+
name: 'click',
217+
});
218+
jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY);
219+
await new Promise(process.nextTick);
220+
221+
// This is still the last replay sent since we passed `continueRecording:
222+
// false`.
223+
expect(replay).toHaveLastSentReplay({
224+
recordingPayloadHeader: { segment_id: 0 },
225+
replayEventPayload: expect.objectContaining({
226+
replay_type: 'error',
227+
contexts: {
228+
replay: {
229+
error_sample_rate: 1,
230+
session_sample_rate: 0,
231+
},
232+
},
233+
}),
234+
recordingData: JSON.stringify([
235+
{ data: { isCheckout: true }, timestamp: BASE_TIMESTAMP, type: 2 },
236+
TEST_EVENT,
237+
{
238+
type: 5,
239+
timestamp: BASE_TIMESTAMP,
240+
data: {
241+
tag: 'breadcrumb',
242+
payload: {
243+
timestamp: BASE_TIMESTAMP / 1000,
244+
type: 'default',
245+
category: 'ui.click',
246+
message: '<unknown>',
247+
data: {},
248+
},
249+
},
250+
},
251+
]),
252+
});
253+
});
254+
161255
it('does not send a replay when triggering a full dom snapshot when document becomes visible after [SESSION_IDLE_DURATION]ms', async () => {
162256
Object.defineProperty(document, 'visibilityState', {
163257
configurable: true,

0 commit comments

Comments
 (0)