Skip to content

Commit cd247f2

Browse files
billyvgc298lee
andauthored
debug(replay): Add debugging statements around event buffer (#14014)
This is not intended to be merged to prod, I would like to debug how/why we keep hitting EventBuffer limits on Sentry SaaS. Aside from debugging statements, there should be no other behavioral changes. --------- Co-authored-by: Catherine Lee <55311782+c298lee@users.noreply.github.com>
1 parent e61f227 commit cd247f2

File tree

5 files changed

+78
-23
lines changed

5 files changed

+78
-23
lines changed

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ module.exports = [
7979
path: 'packages/browser/build/npm/esm/index.js',
8080
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'replayCanvasIntegration'),
8181
gzip: true,
82-
limit: '78 KB',
82+
limit: '80 KB',
8383
},
8484
{
8585
name: '@sentry/browser (incl. Tracing, Replay, Feedback)',

packages/replay-internal/src/eventBuffer/EventBufferCompressionWorker.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ export class EventBufferCompressionWorker implements EventBuffer {
6767
this._totalSize += data.length;
6868

6969
if (this._totalSize > REPLAY_MAX_EVENT_BUFFER_SIZE) {
70+
DEBUG_BUILD &&
71+
logger.info(
72+
`Cannot add new event with raw size of ${data.length} to existing buffer of size ${
73+
this._totalSize - data.length
74+
}`,
75+
);
7076
return Promise.reject(new EventBufferSizeExceededError());
7177
}
7278

@@ -82,14 +88,20 @@ export class EventBufferCompressionWorker implements EventBuffer {
8288

8389
/** @inheritdoc */
8490
public clear(): void {
91+
DEBUG_BUILD && logger.info(`Clearing event buffer (${this._totalSize})`);
8592
this._earliestTimestamp = null;
8693
this._totalSize = 0;
8794
this.hasCheckout = false;
8895

8996
// We do not wait on this, as we assume the order of messages is consistent for the worker
90-
this._worker.postMessage('clear').then(null, e => {
91-
DEBUG_BUILD && logger.exception(e, 'Sending "clear" message to worker failed', e);
92-
});
97+
this._worker.postMessage('clear').then(
98+
() => {
99+
DEBUG_BUILD && logger.info('Event buffer cleared within worker');
100+
},
101+
e => {
102+
DEBUG_BUILD && logger.exception(e, 'Sending "clear" message to worker failed', e);
103+
},
104+
);
93105
}
94106

95107
/** @inheritdoc */

packages/replay-internal/src/eventBuffer/EventBufferProxy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export class EventBufferProxy implements EventBuffer {
115115
// Wait for original events to be re-added before resolving
116116
try {
117117
await Promise.all(addEventPromises);
118+
DEBUG_BUILD && logger.info('Finished switching to compression worker');
118119

119120
// Can now clear fallback buffer as it's no longer necessary
120121
this._fallback.clear();

packages/replay-internal/src/replay.ts

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
/* eslint-disable max-lines */ // TODO: We might want to split this file up
22
import { EventType, record } from '@sentry-internal/rrweb';
3-
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getActiveSpan, getClient, getRootSpan, spanToJSON } from '@sentry/core';
3+
import {
4+
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
5+
getActiveSpan,
6+
getClient,
7+
getRootSpan,
8+
setTag,
9+
spanToJSON,
10+
} from '@sentry/core';
411
import type { ReplayRecordingMode, Span } from '@sentry/types';
512
import { logger } from './util/logger';
613

@@ -1215,28 +1222,14 @@ export class ReplayContainer implements ReplayContainerInterface {
12151222
return;
12161223
}
12171224

1218-
const start = this.session.started;
1219-
const now = Date.now();
1220-
const duration = now - start;
1221-
12221225
// A flush is about to happen, cancel any queued flushes
12231226
this._debouncedFlush.cancel();
12241227

1225-
// If session is too short, or too long (allow some wiggle room over maxReplayDuration), do not send it
1226-
// This _should_ not happen, but it may happen if flush is triggered due to a page activity change or similar
1227-
const tooShort = duration < this._options.minReplayDuration;
1228-
const tooLong = duration > this._options.maxReplayDuration + 5_000;
1229-
if (tooShort || tooLong) {
1230-
DEBUG_BUILD &&
1231-
logger.info(
1232-
`Session duration (${Math.floor(duration / 1000)}s) is too ${
1233-
tooShort ? 'short' : 'long'
1234-
}, not sending replay.`,
1235-
);
1228+
const isValidDuration = this._checkReplayDurationDuringFlush();
12361229

1237-
if (tooShort) {
1238-
this._debouncedFlush();
1239-
}
1230+
// XXX: disregard durations for buffer mode for debug purposes
1231+
if (!isValidDuration && this.recordingMode !== 'buffer') {
1232+
DEBUG_BUILD && logger.info('Invalid duration while buffering');
12401233
return;
12411234
}
12421235

@@ -1272,6 +1265,47 @@ export class ReplayContainer implements ReplayContainerInterface {
12721265
}
12731266
};
12741267

1268+
/**
1269+
* Checks to see if replay duration is within bounds during a flush. If it is
1270+
* too short, will queue up a new flush to prevent short replays.
1271+
*
1272+
* Returns true if duration is ok, false otherwise
1273+
*/
1274+
private _checkReplayDurationDuringFlush(): boolean {
1275+
if (!this.session) {
1276+
return false;
1277+
}
1278+
1279+
const start = this.session.started;
1280+
const now = Date.now();
1281+
const duration = now - start;
1282+
1283+
// If session is too short, or too long (allow some wiggle room over maxReplayDuration), do not send it
1284+
// This _should_ not happen, but it may happen if flush is triggered due to a page activity change or similar
1285+
const tooShort = duration < this._options.minReplayDuration;
1286+
const tooLong = duration > this._options.maxReplayDuration + 5_000;
1287+
if (tooShort || tooLong) {
1288+
DEBUG_BUILD &&
1289+
logger.info(
1290+
`Session duration (${Math.floor(duration / 1000)}s) is too ${
1291+
tooShort ? 'short' : 'long'
1292+
}, not sending replay.`,
1293+
);
1294+
1295+
if (tooShort) {
1296+
this._debouncedFlush();
1297+
}
1298+
1299+
// XXX: disregard durations for buffer mode for debug purposes
1300+
if (this.recordingMode === 'buffer') {
1301+
setTag(`replay.${tooShort ? 'tooShort' : 'tooLong'}`, true);
1302+
}
1303+
return false;
1304+
}
1305+
1306+
return true;
1307+
}
1308+
12751309
/** Save the session, if it is sticky */
12761310
private _maybeSaveSession(): void {
12771311
if (this.session && this._options.stickySession) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCa
4343
// dependent on this reset.
4444
if (replay.recordingMode === 'buffer' && isCheckout) {
4545
replay.setInitialState();
46+
DEBUG_BUILD && logger.info(`Adding checkout event while in buffer mode (${JSON.stringify(event).length})`);
4647
}
4748

4849
// If the event is not added (e.g. due to being paused, disabled, or out of the max replay duration),
@@ -74,7 +75,11 @@ export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCa
7475
// When in buffer mode, make sure we adjust the session started date to the current earliest event of the buffer
7576
// this should usually be the timestamp of the checkout event, but to be safe...
7677
if (replay.recordingMode === 'buffer' && session && replay.eventBuffer) {
78+
DEBUG_BUILD &&
79+
logger.info('Attempting to fetch earliest event from event buffer type: ', replay.eventBuffer.type);
80+
7781
const earliestEvent = replay.eventBuffer.getEarliestTimestamp();
82+
7883
if (earliestEvent) {
7984
DEBUG_BUILD &&
8085
logger.info(`Updating session start time to earliest event in buffer to ${new Date(earliestEvent)}`);
@@ -84,6 +89,9 @@ export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCa
8489
if (replay.getOptions().stickySession) {
8590
saveSession(session);
8691
}
92+
} else {
93+
// XXX(billy): debugging
94+
DEBUG_BUILD && logger.warn('Unable to find earliest event in event buffer');
8795
}
8896
}
8997

0 commit comments

Comments
 (0)