-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix(replay): Do not renew session in error mode #6948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
import { captureException } from '@sentry/core'; | ||
import { captureException, getCurrentHub } from '@sentry/core'; | ||
|
||
import { | ||
DEFAULT_FLUSH_MIN_DELAY, | ||
ERROR_CHECKOUT_TIME, | ||
MAX_SESSION_LIFE, | ||
REPLAY_SESSION_KEY, | ||
VISIBILITY_CHANGE_TIMEOUT, | ||
WINDOW, | ||
|
@@ -264,12 +265,10 @@ describe('Integration | errorSampleRate', () => { | |
expect(replay).not.toHaveLastSentReplay(); | ||
}); | ||
|
||
it('does not upload if user has been idle for more than 15 minutes and comes back to move their mouse', async () => { | ||
it('stops replay if user has been idle for more than 15 minutes and comes back to move their mouse', async () => { | ||
// Idle for 15 minutes | ||
jest.advanceTimersByTime(15 * 60000); | ||
|
||
// TBD: We are currently deciding that this event will get dropped, but | ||
// this could/should change in the future. | ||
const TEST_EVENT = { | ||
data: { name: 'lost event' }, | ||
timestamp: BASE_TIMESTAMP, | ||
|
@@ -281,15 +280,11 @@ describe('Integration | errorSampleRate', () => { | |
jest.runAllTimers(); | ||
await new Promise(process.nextTick); | ||
|
||
// Instead of recording the above event, a full snapshot will occur. | ||
// | ||
// TODO: We could potentially figure out a way to save the last session, | ||
// and produce a checkout based on a previous checkout + updates, and then | ||
// replay the event on top. Or maybe replay the event on top of a refresh | ||
// snapshot. | ||
// We stop recording after 15 minutes of inactivity in error mode | ||
|
||
expect(replay).not.toHaveLastSentReplay(); | ||
expect(mockRecord.takeFullSnapshot).toHaveBeenCalledWith(true); | ||
expect(replay.isEnabled()).toBe(false); | ||
expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('has the correct timestamps with deferred root event and last replay update', async () => { | ||
|
@@ -375,6 +370,52 @@ describe('Integration | errorSampleRate', () => { | |
]), | ||
}); | ||
}); | ||
|
||
it('stops replay when session expires', async () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We only want this for the error mode, right? Do we have tests in the session recording mode that check the expected behavior there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this existing test should cover this: https://github.com/getsentry/sentry-javascript/blob/master/packages/replay/test/integration/session.test.ts#L106 |
||
jest.setSystemTime(BASE_TIMESTAMP); | ||
|
||
const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; | ||
mockRecord._emitter(TEST_EVENT); | ||
|
||
expect(mockRecord.takeFullSnapshot).not.toHaveBeenCalled(); | ||
expect(replay).not.toHaveLastSentReplay(); | ||
|
||
jest.runAllTimers(); | ||
await new Promise(process.nextTick); | ||
|
||
captureException(new Error('testing')); | ||
|
||
jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY); | ||
await new Promise(process.nextTick); | ||
|
||
expect(replay).toHaveLastSentReplay(); | ||
|
||
// Wait a bit, shortly before session expires | ||
jest.advanceTimersByTime(MAX_SESSION_LIFE - 1000); | ||
await new Promise(process.nextTick); | ||
|
||
mockRecord._emitter(TEST_EVENT); | ||
replay.triggerUserActivity(); | ||
|
||
expect(replay).toHaveLastSentReplay(); | ||
|
||
// Now wait after session expires - should stop recording | ||
mockRecord.takeFullSnapshot.mockClear(); | ||
(getCurrentHub().getClient()!.getTransport()!.send as unknown as jest.SpyInstance<any>).mockClear(); | ||
|
||
jest.advanceTimersByTime(10_000); | ||
await new Promise(process.nextTick); | ||
|
||
mockRecord._emitter(TEST_EVENT); | ||
replay.triggerUserActivity(); | ||
|
||
jest.advanceTimersByTime(DEFAULT_FLUSH_MIN_DELAY); | ||
await new Promise(process.nextTick); | ||
|
||
expect(replay).not.toHaveLastSentReplay(); | ||
expect(mockRecord.takeFullSnapshot).toHaveBeenCalledTimes(0); | ||
expect(replay.isEnabled()).toBe(false); | ||
}); | ||
}); | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this check to ensure we do not stop multiple times.