rollbar 3.0.0-beta.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.git-blame-ignore-revs +3 -1
- package/AGENTS.md +21 -0
- package/CONTRIBUTING.md +68 -73
- package/babel.config.json +7 -0
- package/bower.json +1 -1
- package/dist/plugins/jquery.min.js +1 -1
- package/dist/rollbar.cjs +2216 -2022
- package/dist/rollbar.js +6098 -5886
- package/dist/rollbar.js.map +1 -1
- package/dist/rollbar.min.cjs +1 -1
- package/dist/rollbar.min.cjs.LICENSE.txt +1 -1
- package/dist/rollbar.min.js +1 -1
- package/dist/rollbar.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.min.js.map +1 -1
- package/dist/rollbar.named-amd.js +6097 -5886
- package/dist/rollbar.named-amd.js.map +1 -1
- package/dist/rollbar.named-amd.min.js +1 -1
- package/dist/rollbar.named-amd.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.named-amd.min.js.map +1 -1
- package/dist/rollbar.noconflict.umd.js +6097 -5886
- package/dist/rollbar.noconflict.umd.js.map +1 -1
- package/dist/rollbar.noconflict.umd.min.js +1 -1
- package/dist/rollbar.noconflict.umd.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.noconflict.umd.min.js.map +1 -1
- package/dist/rollbar.replay.js +8123 -7924
- package/dist/rollbar.replay.js.map +1 -1
- package/dist/rollbar.replay.min.js +1 -1
- package/dist/rollbar.replay.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.replay.min.js.map +1 -1
- package/dist/rollbar.replay.noconflict.umd.js +8122 -7924
- package/dist/rollbar.replay.noconflict.umd.js.map +1 -1
- package/dist/rollbar.replay.noconflict.umd.min.js +1 -1
- package/dist/rollbar.replay.noconflict.umd.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.replay.noconflict.umd.min.js.map +1 -1
- package/dist/rollbar.replay.umd.js +8122 -7924
- package/dist/rollbar.replay.umd.js.map +1 -1
- package/dist/rollbar.replay.umd.min.js +1 -1
- package/dist/rollbar.replay.umd.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.replay.umd.min.js.map +1 -1
- package/dist/rollbar.snippet.js +1 -1
- package/dist/rollbar.umd.js +6097 -5886
- package/dist/rollbar.umd.js.map +1 -1
- package/dist/rollbar.umd.min.js +1 -1
- package/dist/rollbar.umd.min.js.LICENSE.txt +1 -1
- package/dist/rollbar.umd.min.js.map +1 -1
- package/eslint.config.js +151 -0
- package/index.d.ts +45 -13
- package/package.json +26 -6
- package/src/api.js +130 -136
- package/src/apiUtility.js +2 -2
- package/src/browser/bundles/rollbar.snippet.js +1 -0
- package/src/browser/core.js +31 -42
- package/src/browser/domUtility.js +11 -17
- package/src/browser/globalSetup.js +3 -3
- package/src/browser/replay/checkoutWatchdog.js +104 -0
- package/src/browser/replay/recorder.d.ts +5 -2
- package/src/browser/replay/recorder.js +22 -4
- package/src/browser/replay/replay.js +8 -4
- package/src/browser/replay/replayPredicates.js +1 -1
- package/src/browser/rollbar.js +5 -4
- package/src/browser/rollbarReplay.js +6 -5
- package/src/browser/rollbarWrapper.js +2 -2
- package/src/browser/shim.js +15 -15
- package/src/browser/telemetry.js +26 -22
- package/src/browser/transforms.js +4 -4
- package/src/browser/transport/xhr.js +4 -4
- package/src/browser/transport.js +9 -10
- package/src/browser/wrapGlobals.js +3 -4
- package/src/defaults.js +1 -1
- package/src/errorParser.js +1 -1
- package/src/logger.js +1 -0
- package/src/notifier.js +102 -100
- package/src/predicates.js +3 -4
- package/src/rateLimiter.js +107 -104
- package/src/react-native/rollbar.js +9 -10
- package/src/react-native/transforms.js +4 -5
- package/src/react-native/transport.js +7 -7
- package/src/rollbar.js +7 -4
- package/src/scrub.js +16 -20
- package/src/server/locals.js +7 -7
- package/src/server/parser.js +9 -6
- package/src/server/rollbar.js +54 -49
- package/src/server/sourceMap/stackTrace.js +7 -6
- package/src/server/telemetry/urlHelpers.js +2 -1
- package/src/server/telemetry.js +10 -10
- package/src/server/transforms.js +10 -6
- package/src/server/transport.js +8 -7
- package/src/telemetry.js +22 -25
- package/src/tracing/tracer.js +2 -2
- package/src/tracing/tracing.js +2 -2
- package/src/truncation.js +6 -6
- package/src/utility/headers.js +4 -2
- package/src/utility/traverse.js +1 -1
- package/src/utility.js +111 -33
- package/tsconfig.json +16 -0
- package/tsconfig.test.json +10 -0
- package/{web-test-runner.config.mjs → web-test-runner.config.js} +10 -0
- package/{webpack.config.cjs → webpack.config.js} +39 -27
- package/.eslintrc +0 -27
- package/eslint.config.mjs +0 -33
- package/src/merge.js +0 -61
package/src/browser/core.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import Client from '../rollbar.js';
|
|
2
|
-
import * as _ from '../utility.js';
|
|
3
1
|
import API from '../api.js';
|
|
2
|
+
import defaults from '../defaults.js';
|
|
3
|
+
import errorParser from '../errorParser.js';
|
|
4
4
|
import logger from '../logger.js';
|
|
5
|
-
import * as
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import * as urllib from './url.js';
|
|
9
|
-
|
|
10
|
-
import * as transforms from './transforms.js';
|
|
5
|
+
import * as sharedPredicates from '../predicates.js';
|
|
6
|
+
import Client from '../rollbar.js';
|
|
7
|
+
import tracingDefaults from '../tracing/defaults.js';
|
|
11
8
|
import * as sharedTransforms from '../transforms.js';
|
|
9
|
+
import * as _ from '../utility.js';
|
|
10
|
+
|
|
11
|
+
import browserDefaults from './defaults.js';
|
|
12
|
+
import * as globals from './globalSetup.js';
|
|
12
13
|
import * as predicates from './predicates.js';
|
|
13
|
-
import * as sharedPredicates from '../predicates.js';
|
|
14
|
-
import errorParser from '../errorParser.js';
|
|
15
14
|
import replayDefaults from './replay/defaults.js';
|
|
16
|
-
import
|
|
15
|
+
import * as transforms from './transforms.js';
|
|
16
|
+
import Transport from './transport.js';
|
|
17
|
+
import * as urllib from './url.js';
|
|
17
18
|
|
|
18
19
|
// Used to support global `Rollbar` instance.
|
|
19
20
|
let _instance = null;
|
|
@@ -67,7 +68,7 @@ class Rollbar {
|
|
|
67
68
|
'browser',
|
|
68
69
|
);
|
|
69
70
|
var gWindow = _gWindow();
|
|
70
|
-
var gDocument = typeof document
|
|
71
|
+
var gDocument = typeof document !== 'undefined' && document;
|
|
71
72
|
this.isChrome = gWindow.chrome && gWindow.chrome.runtime; // check .runtime to avoid Edge browsers
|
|
72
73
|
this.anonymousErrorsPending = 0;
|
|
73
74
|
addTransformsToNotifier(this.client.notifier, this, gWindow);
|
|
@@ -126,7 +127,7 @@ class Rollbar {
|
|
|
126
127
|
);
|
|
127
128
|
|
|
128
129
|
this.tracing?.configure(this.options);
|
|
129
|
-
this.replay?.configure(this.options);
|
|
130
|
+
this.replay?.configure(this.options.replay);
|
|
130
131
|
this.client.configure(this.options, payloadData);
|
|
131
132
|
this.instrumenter?.configure(this.options);
|
|
132
133
|
this.setupUnhandledCapture();
|
|
@@ -294,16 +295,15 @@ class Rollbar {
|
|
|
294
295
|
return;
|
|
295
296
|
}
|
|
296
297
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (r.anonymousErrorsPending) {
|
|
298
|
+
const prepareStackTrace = (error, _stack) => {
|
|
299
|
+
if (this.options.inspectAnonymousErrors) {
|
|
300
|
+
if (this.anonymousErrorsPending) {
|
|
301
301
|
// This is the only known way to detect that onerror saw an anonymous error.
|
|
302
302
|
// It depends on onerror reliably being called before Error.prepareStackTrace,
|
|
303
303
|
// which so far holds true on tested versions of Chrome. If versions of Chrome
|
|
304
304
|
// are tested that behave differently, this logic will need to be updated
|
|
305
305
|
// accordingly.
|
|
306
|
-
|
|
306
|
+
this.anonymousErrorsPending -= 1;
|
|
307
307
|
|
|
308
308
|
if (!error) {
|
|
309
309
|
// Not likely to get here, but calling handleUncaughtException from here
|
|
@@ -318,13 +318,13 @@ class Rollbar {
|
|
|
318
318
|
// url, lineno, colno shouldn't be needed for these errors.
|
|
319
319
|
// If that changes, update this accordingly, using the unused
|
|
320
320
|
// _stack param as needed (rather than parse error.toString()).
|
|
321
|
-
|
|
321
|
+
this.handleUncaughtException(error.message, null, null, null, error);
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
// Workaround to ensure stack is preserved for normal errors.
|
|
326
326
|
return error.stack;
|
|
327
|
-
}
|
|
327
|
+
};
|
|
328
328
|
|
|
329
329
|
// https://v8.dev/docs/stack-trace-api
|
|
330
330
|
try {
|
|
@@ -424,17 +424,15 @@ class Rollbar {
|
|
|
424
424
|
|
|
425
425
|
f._rollbar_wrapped._isWrap = true;
|
|
426
426
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
f._rollbar_wrapped[prop] = f[prop];
|
|
431
|
-
}
|
|
427
|
+
for (var prop in f) {
|
|
428
|
+
if (_.hasOwn(f, prop) && prop !== '_rollbar_wrapped') {
|
|
429
|
+
f._rollbar_wrapped[prop] = f[prop];
|
|
432
430
|
}
|
|
433
431
|
}
|
|
434
432
|
}
|
|
435
433
|
|
|
436
434
|
return f._rollbar_wrapped;
|
|
437
|
-
} catch (
|
|
435
|
+
} catch (_e) {
|
|
438
436
|
// Return the original function if the wrap fails.
|
|
439
437
|
return f;
|
|
440
438
|
}
|
|
@@ -582,28 +580,19 @@ function _getFirstFunction(args) {
|
|
|
582
580
|
|
|
583
581
|
function _gWindow() {
|
|
584
582
|
return (
|
|
585
|
-
(typeof window
|
|
586
|
-
(typeof self
|
|
583
|
+
(typeof window !== 'undefined' && window) ||
|
|
584
|
+
(typeof self !== 'undefined' && self)
|
|
587
585
|
);
|
|
588
586
|
}
|
|
589
587
|
|
|
590
|
-
import {
|
|
591
|
-
version,
|
|
592
|
-
logLevel,
|
|
593
|
-
reportLevel,
|
|
594
|
-
uncaughtErrorLevel,
|
|
595
|
-
endpoint,
|
|
596
|
-
} from '../defaults.js';
|
|
597
|
-
import browserDefaults from './defaults.js';
|
|
598
|
-
|
|
599
588
|
const defaultOptions = {
|
|
600
589
|
environment: 'unknown',
|
|
601
|
-
version: version,
|
|
590
|
+
version: defaults.version,
|
|
602
591
|
scrubFields: browserDefaults.scrubFields,
|
|
603
|
-
logLevel: logLevel,
|
|
604
|
-
reportLevel: reportLevel,
|
|
605
|
-
uncaughtErrorLevel: uncaughtErrorLevel,
|
|
606
|
-
endpoint: endpoint,
|
|
592
|
+
logLevel: defaults.logLevel,
|
|
593
|
+
reportLevel: defaults.reportLevel,
|
|
594
|
+
uncaughtErrorLevel: defaults.uncaughtErrorLevel,
|
|
595
|
+
endpoint: defaults.endpoint,
|
|
607
596
|
verbose: false,
|
|
608
597
|
enabled: true,
|
|
609
598
|
transmit: true,
|
|
@@ -9,9 +9,9 @@ function isDescribedElement(element, type, subtypes) {
|
|
|
9
9
|
if (!subtypes) {
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
for (
|
|
14
|
-
if (
|
|
12
|
+
const elementType = getElementType(element);
|
|
13
|
+
for (const subtype of subtypes) {
|
|
14
|
+
if (subtype === elementType) {
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -34,7 +34,7 @@ function treeToArray(elem) {
|
|
|
34
34
|
var nextDescription;
|
|
35
35
|
for (var height = 0; elem && height < MAX_HEIGHT; height++) {
|
|
36
36
|
nextDescription = describeElement(elem);
|
|
37
|
-
if (nextDescription.tagName === 'html') {
|
|
37
|
+
if (!nextDescription || nextDescription.tagName === 'html') {
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
out.unshift(nextDescription);
|
|
@@ -80,10 +80,8 @@ function descriptionToString(desc) {
|
|
|
80
80
|
if (desc.classes) {
|
|
81
81
|
out.push('.' + desc.classes.join('.'));
|
|
82
82
|
}
|
|
83
|
-
for (
|
|
84
|
-
out.push(
|
|
85
|
-
'[' + desc.attributes[i].key + '="' + desc.attributes[i].value + '"]',
|
|
86
|
-
);
|
|
83
|
+
for (const attribute of desc.attributes) {
|
|
84
|
+
out.push('[' + attribute.key + '="' + attribute.value + '"]');
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
return out.join('');
|
|
@@ -109,10 +107,7 @@ function describeElement(elem) {
|
|
|
109
107
|
return null;
|
|
110
108
|
}
|
|
111
109
|
var out = {},
|
|
112
|
-
className
|
|
113
|
-
key,
|
|
114
|
-
attr,
|
|
115
|
-
i;
|
|
110
|
+
className;
|
|
116
111
|
out.tagName = elem.tagName.toLowerCase();
|
|
117
112
|
if (elem.id) {
|
|
118
113
|
out.id = elem.id;
|
|
@@ -123,11 +118,10 @@ function describeElement(elem) {
|
|
|
123
118
|
}
|
|
124
119
|
var attributes = ['type', 'name', 'title', 'alt'];
|
|
125
120
|
out.attributes = [];
|
|
126
|
-
for (
|
|
127
|
-
|
|
128
|
-
attr = elem.getAttribute(key);
|
|
121
|
+
for (const attribute of attributes) {
|
|
122
|
+
const attr = elem.getAttribute(attribute);
|
|
129
123
|
if (attr) {
|
|
130
|
-
out.attributes.push({ key:
|
|
124
|
+
out.attributes.push({ key: attribute, value: attr });
|
|
131
125
|
}
|
|
132
126
|
}
|
|
133
127
|
return out;
|
|
@@ -161,7 +155,7 @@ function isMatchingElement(element, classes, selectors) {
|
|
|
161
155
|
return true;
|
|
162
156
|
}
|
|
163
157
|
}
|
|
164
|
-
} catch (
|
|
158
|
+
} catch (_e) {
|
|
165
159
|
// ignore errors from invalid arguments
|
|
166
160
|
}
|
|
167
161
|
return false;
|
|
@@ -67,12 +67,12 @@ function captureUnhandledRejections(window, handler, shim) {
|
|
|
67
67
|
var reason, promise, detail;
|
|
68
68
|
try {
|
|
69
69
|
reason = evt.reason;
|
|
70
|
-
} catch (
|
|
70
|
+
} catch (_e) {
|
|
71
71
|
reason = undefined;
|
|
72
72
|
}
|
|
73
73
|
try {
|
|
74
74
|
promise = evt.promise;
|
|
75
|
-
} catch (
|
|
75
|
+
} catch (_e) {
|
|
76
76
|
promise = '[unhandledrejection] error getting `promise` from event';
|
|
77
77
|
}
|
|
78
78
|
try {
|
|
@@ -81,7 +81,7 @@ function captureUnhandledRejections(window, handler, shim) {
|
|
|
81
81
|
reason = detail.reason;
|
|
82
82
|
promise = detail.promise;
|
|
83
83
|
}
|
|
84
|
-
} catch (
|
|
84
|
+
} catch (_e) {
|
|
85
85
|
// Ignore
|
|
86
86
|
}
|
|
87
87
|
if (!reason) {
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import logger from '../../logger.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Schedules forced rrweb checkouts when the recorder has been idle too long.
|
|
5
|
+
*
|
|
6
|
+
* Recorder notifies the watchdog whenever rrweb performs a checkout. If
|
|
7
|
+
* another checkout doesn't happen within the configured window, the watchdog
|
|
8
|
+
* calls `forceCheckout` so buffers stay within max pre-duration limits.
|
|
9
|
+
*/
|
|
10
|
+
export default class CheckoutWatchdog {
|
|
11
|
+
_getIntervalMs;
|
|
12
|
+
_forceCheckout;
|
|
13
|
+
_marginMs;
|
|
14
|
+
_now;
|
|
15
|
+
|
|
16
|
+
_timerId = null;
|
|
17
|
+
_lastCheckoutAt = null;
|
|
18
|
+
_running = false;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @param {() => number} params.getIntervalMs - Returns checkout interval
|
|
23
|
+
* @param {() => void} params.forceCheckout - Invoked to force a checkout
|
|
24
|
+
* @param {number} [params.marginMs] - Safety margin before forcing checkout, default: 1000ms
|
|
25
|
+
* @param {() => number} [params.now] - Clock function (primarily for tests), default: Date.now
|
|
26
|
+
*/
|
|
27
|
+
constructor({
|
|
28
|
+
getIntervalMs,
|
|
29
|
+
forceCheckout,
|
|
30
|
+
marginMs = 1000,
|
|
31
|
+
now = () => Date.now(),
|
|
32
|
+
}) {
|
|
33
|
+
this._getIntervalMs = getIntervalMs;
|
|
34
|
+
this._forceCheckout = forceCheckout;
|
|
35
|
+
this._marginMs = marginMs;
|
|
36
|
+
this._now = now;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
start() {
|
|
40
|
+
if (this._running) return;
|
|
41
|
+
|
|
42
|
+
this._running = true;
|
|
43
|
+
this._lastCheckoutAt = this._now();
|
|
44
|
+
this._arm();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
stop() {
|
|
48
|
+
if (!this._running) return;
|
|
49
|
+
|
|
50
|
+
this._running = false;
|
|
51
|
+
this._lastCheckoutAt = null;
|
|
52
|
+
this._clearTimer();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Notifies the watchdog that rrweb just performed a checkout.
|
|
57
|
+
*
|
|
58
|
+
* @param {number} [timestamp] - Timestamp of checkout (ms)
|
|
59
|
+
*/
|
|
60
|
+
notify(timestamp = this._now()) {
|
|
61
|
+
if (!this._running) return;
|
|
62
|
+
|
|
63
|
+
this._lastCheckoutAt = timestamp;
|
|
64
|
+
this._arm();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
_arm() {
|
|
68
|
+
this._clearTimer();
|
|
69
|
+
|
|
70
|
+
if (!this._running) return;
|
|
71
|
+
|
|
72
|
+
const delay = this._getIntervalMs() + this._marginMs;
|
|
73
|
+
this._timerId = setTimeout(() => this._maybeForceCheckout(), delay);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_maybeForceCheckout() {
|
|
77
|
+
if (!this._running) return;
|
|
78
|
+
|
|
79
|
+
const interval = this._getIntervalMs();
|
|
80
|
+
const lastCheckoutAt = this._lastCheckoutAt ?? this._now();
|
|
81
|
+
const delta = this._now() - lastCheckoutAt;
|
|
82
|
+
|
|
83
|
+
if (delta < interval) {
|
|
84
|
+
this._arm();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
this._forceCheckout();
|
|
90
|
+
} catch (error) {
|
|
91
|
+
logger.error('Replay: Forced checkout failed', error);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this._lastCheckoutAt = this._now();
|
|
95
|
+
this._arm();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
_clearTimer() {
|
|
99
|
+
if (this._timerId) {
|
|
100
|
+
clearTimeout(this._timerId);
|
|
101
|
+
this._timerId = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** A point-in-time cursor into the active Recorder's two-slot ring buffer. */
|
|
2
|
-
export
|
|
2
|
+
export interface BufferCursor {
|
|
3
3
|
/** Index (0|1) of the active buffer's slot at snapshot time. */
|
|
4
4
|
slot: 0 | 1;
|
|
5
5
|
/**
|
|
@@ -7,7 +7,7 @@ export type BufferCursor = {
|
|
|
7
7
|
* May be -1 when empty.
|
|
8
8
|
*/
|
|
9
9
|
offset: number;
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
|
|
12
12
|
export default class Recorder {
|
|
13
13
|
constructor(options: Record<string, any>);
|
|
@@ -28,4 +28,7 @@ export default class Recorder {
|
|
|
28
28
|
start(): this;
|
|
29
29
|
stop(): this;
|
|
30
30
|
clear(): void;
|
|
31
|
+
|
|
32
|
+
// Internal only - for testing
|
|
33
|
+
get _recordFn(): (event: any) => void;
|
|
31
34
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { record as rrwebRecordFn } from '@rrweb/record';
|
|
2
2
|
import { EventType } from '@rrweb/types';
|
|
3
3
|
|
|
4
|
-
import hrtime from '../../tracing/hrtime.js';
|
|
5
4
|
import logger from '../../logger.js';
|
|
5
|
+
import hrtime from '../../tracing/hrtime.js';
|
|
6
|
+
import { isFunction } from '../../utility.js';
|
|
7
|
+
|
|
8
|
+
import CheckoutWatchdog from './checkoutWatchdog.js';
|
|
6
9
|
|
|
7
10
|
/** @typedef {import('./recorder.js').BufferCursor} BufferCursor */
|
|
8
11
|
|
|
@@ -13,6 +16,7 @@ export default class Recorder {
|
|
|
13
16
|
_isReady = false;
|
|
14
17
|
_stopFn = null;
|
|
15
18
|
_recordFn;
|
|
19
|
+
_checkoutWatchdog;
|
|
16
20
|
|
|
17
21
|
/** A two-slot ring buffer for storing events. */
|
|
18
22
|
_buffers = [[], []];
|
|
@@ -28,11 +32,20 @@ export default class Recorder {
|
|
|
28
32
|
*
|
|
29
33
|
* @param {Object} options - Configuration options for the recorder
|
|
30
34
|
*/
|
|
31
|
-
constructor(options) {
|
|
35
|
+
constructor(options = {}) {
|
|
32
36
|
this.options = options;
|
|
33
37
|
|
|
34
38
|
// Tests inject a custom rrweb record function or mock.
|
|
35
39
|
this._recordFn = options.recordFn || rrwebRecordFn;
|
|
40
|
+
|
|
41
|
+
if (!isFunction(this._recordFn?.takeFullSnapshot)) {
|
|
42
|
+
throw new Error('Recorder requires a valid rrweb record function');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this._checkoutWatchdog = new CheckoutWatchdog({
|
|
46
|
+
getIntervalMs: () => this.checkoutEveryNms(),
|
|
47
|
+
forceCheckout: () => this._recordFn.takeFullSnapshot(true),
|
|
48
|
+
});
|
|
36
49
|
}
|
|
37
50
|
|
|
38
51
|
get isRecording() {
|
|
@@ -60,8 +73,8 @@ export default class Recorder {
|
|
|
60
73
|
debug,
|
|
61
74
|
|
|
62
75
|
// disallowed rrweb options
|
|
63
|
-
emit,
|
|
64
|
-
checkoutEveryNms,
|
|
76
|
+
emit: _emit,
|
|
77
|
+
checkoutEveryNms: _checkoutEveryNms,
|
|
65
78
|
|
|
66
79
|
// rrweb options
|
|
67
80
|
...rrwebOptions
|
|
@@ -176,6 +189,7 @@ export default class Recorder {
|
|
|
176
189
|
if (isCheckout && event.type === EventType.Meta) {
|
|
177
190
|
this._currentSlot = this._previousSlot;
|
|
178
191
|
this._buffers[this._currentSlot] = [];
|
|
192
|
+
this._checkoutWatchdog.notify(event.timestamp);
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
this._buffers[this._currentSlot].push(event);
|
|
@@ -190,6 +204,8 @@ export default class Recorder {
|
|
|
190
204
|
...this._rrwebOptions,
|
|
191
205
|
});
|
|
192
206
|
|
|
207
|
+
this._checkoutWatchdog.start();
|
|
208
|
+
|
|
193
209
|
return this;
|
|
194
210
|
}
|
|
195
211
|
|
|
@@ -201,6 +217,7 @@ export default class Recorder {
|
|
|
201
217
|
this._stopFn();
|
|
202
218
|
this._stopFn = null;
|
|
203
219
|
this._isReady = false;
|
|
220
|
+
this._checkoutWatchdog.stop();
|
|
204
221
|
|
|
205
222
|
return this;
|
|
206
223
|
}
|
|
@@ -209,6 +226,7 @@ export default class Recorder {
|
|
|
209
226
|
this._buffers = [[], []];
|
|
210
227
|
this._currentSlot = 0;
|
|
211
228
|
this._isReady = false;
|
|
229
|
+
this._checkoutWatchdog.stop();
|
|
212
230
|
}
|
|
213
231
|
|
|
214
232
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import logger from '../../logger.js';
|
|
2
2
|
import hrtime from '../../tracing/hrtime.js';
|
|
3
3
|
import id from '../../tracing/id.js';
|
|
4
|
-
import
|
|
4
|
+
import * as _ from '../../utility.js';
|
|
5
|
+
|
|
5
6
|
import Recorder from './recorder.js';
|
|
6
7
|
import ReplayPredicates from './replayPredicates.js';
|
|
7
|
-
import ScheduledCapture from './scheduledCapture.js';
|
|
8
8
|
import ScheduledStreamCapture from './scheduledStreamCapture.js';
|
|
9
9
|
|
|
10
10
|
/** @typedef {import('./recorder.js').BufferCursor} BufferCursor */
|
|
@@ -28,6 +28,7 @@ const TrailingStatus = Object.freeze({
|
|
|
28
28
|
*/
|
|
29
29
|
export default class Replay {
|
|
30
30
|
_map;
|
|
31
|
+
_options;
|
|
31
32
|
/** @type {Recorder} */
|
|
32
33
|
_recorder;
|
|
33
34
|
_tracing;
|
|
@@ -48,6 +49,7 @@ export default class Replay {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
this._map = new Map();
|
|
52
|
+
this._options = options;
|
|
51
53
|
this._predicates = new ReplayPredicates(options);
|
|
52
54
|
this._recorder = new Recorder({
|
|
53
55
|
...options,
|
|
@@ -93,6 +95,7 @@ export default class Replay {
|
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
configure(options) {
|
|
98
|
+
this._options = options;
|
|
96
99
|
this._predicates.configure(options);
|
|
97
100
|
this._recorder.configure({
|
|
98
101
|
...options,
|
|
@@ -125,6 +128,7 @@ export default class Replay {
|
|
|
125
128
|
'rollbar.replay.trigger.context': JSON.stringify(triggerContext),
|
|
126
129
|
'rollbar.replay.trigger': JSON.stringify(trigger),
|
|
127
130
|
'rollbar.replay.url.full': _.sanitizeHref(window.location.href),
|
|
131
|
+
'rollbar.replay.options': JSON.stringify(this._options || {}),
|
|
128
132
|
});
|
|
129
133
|
} catch (error) {
|
|
130
134
|
// TODO(matux): No events probably, this is expected, be more graceful.
|
|
@@ -227,7 +231,7 @@ export default class Replay {
|
|
|
227
231
|
|
|
228
232
|
try {
|
|
229
233
|
await this.send(replayId);
|
|
230
|
-
} catch (
|
|
234
|
+
} catch (_error) {
|
|
231
235
|
this.discard(replayId);
|
|
232
236
|
return null;
|
|
233
237
|
}
|
package/src/browser/rollbar.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import scrub from '../scrub.js';
|
|
2
2
|
import Telemeter from '../telemetry.js';
|
|
3
|
+
import Tracing from '../tracing/tracing.js';
|
|
4
|
+
import truncation from '../truncation.js';
|
|
5
|
+
|
|
6
|
+
import Rollbar from './core.js';
|
|
3
7
|
import Instrumenter from './telemetry.js';
|
|
4
8
|
import wrapGlobals from './wrapGlobals.js';
|
|
5
|
-
import scrub from '../scrub.js';
|
|
6
|
-
import truncation from '../truncation.js';
|
|
7
|
-
import Tracing from '../tracing/tracing.js';
|
|
8
9
|
|
|
9
10
|
Rollbar.setComponents({
|
|
10
11
|
telemeter: Telemeter,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import Rollbar from './core.js';
|
|
2
|
-
import Telemeter from '../telemetry.js';
|
|
3
|
-
import Instrumenter from './telemetry.js';
|
|
4
|
-
import wrapGlobals from './wrapGlobals.js';
|
|
5
1
|
import scrub from '../scrub.js';
|
|
6
|
-
import
|
|
2
|
+
import Telemeter from '../telemetry.js';
|
|
7
3
|
import Tracing from '../tracing/tracing.js';
|
|
4
|
+
import truncation from '../truncation.js';
|
|
5
|
+
|
|
6
|
+
import Rollbar from './core.js';
|
|
8
7
|
import Replay from './replay/replay.js';
|
|
8
|
+
import Instrumenter from './telemetry.js';
|
|
9
|
+
import wrapGlobals from './wrapGlobals.js';
|
|
9
10
|
|
|
10
11
|
Rollbar.setComponents({
|
|
11
12
|
telemeter: Telemeter,
|
|
@@ -18,8 +18,8 @@ function _setupForwarding(prototype) {
|
|
|
18
18
|
'log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleAnonymousErrors,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad'.split(
|
|
19
19
|
',',
|
|
20
20
|
);
|
|
21
|
-
for (
|
|
22
|
-
prototype[
|
|
21
|
+
for (const method of _methods) {
|
|
22
|
+
prototype[method] = _forward(method);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
package/src/browser/shim.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import logger from '../logger.js';
|
|
2
|
+
import { hasOwn } from '../utility.js';
|
|
3
|
+
|
|
1
4
|
import * as globals from './globalSetup.js';
|
|
5
|
+
import Wrapper from './rollbarWrapper.js';
|
|
2
6
|
import wrapGlobals from './wrapGlobals.js';
|
|
3
7
|
|
|
4
8
|
function _wrapInternalErr(f) {
|
|
@@ -7,8 +11,8 @@ function _wrapInternalErr(f) {
|
|
|
7
11
|
return f.apply(this, arguments);
|
|
8
12
|
} catch (e) {
|
|
9
13
|
try {
|
|
10
|
-
|
|
11
|
-
} catch (
|
|
14
|
+
logger.error('[Rollbar]: Internal error', e);
|
|
15
|
+
} catch (_e2) {
|
|
12
16
|
// Ignore
|
|
13
17
|
}
|
|
14
18
|
}
|
|
@@ -28,7 +32,6 @@ function Shim(options, wrap) {
|
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
import Wrapper from './rollbarWrapper.js';
|
|
32
35
|
var ShimImpl = function (options, wrap) {
|
|
33
36
|
return new Shim(options, wrap);
|
|
34
37
|
};
|
|
@@ -144,7 +147,7 @@ Shim.prototype.loadFull = function (
|
|
|
144
147
|
s.onload = s.onreadystatechange = null;
|
|
145
148
|
try {
|
|
146
149
|
parentNode.removeChild(s);
|
|
147
|
-
} catch (
|
|
150
|
+
} catch (_e) {
|
|
148
151
|
// pass
|
|
149
152
|
}
|
|
150
153
|
done = true;
|
|
@@ -198,17 +201,15 @@ Shim.prototype.wrap = function (f, context, _before) {
|
|
|
198
201
|
|
|
199
202
|
f._rollbar_wrapped._isWrap = true;
|
|
200
203
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
f._rollbar_wrapped[prop] = f[prop];
|
|
205
|
-
}
|
|
204
|
+
for (var prop in f) {
|
|
205
|
+
if (hasOwn(f, prop)) {
|
|
206
|
+
f._rollbar_wrapped[prop] = f[prop];
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
return f._rollbar_wrapped;
|
|
211
|
-
} catch (
|
|
212
|
+
} catch (_e) {
|
|
212
213
|
// Return the original function if the wrap fails.
|
|
213
214
|
return f;
|
|
214
215
|
}
|
|
@@ -216,9 +217,8 @@ Shim.prototype.wrap = function (f, context, _before) {
|
|
|
216
217
|
|
|
217
218
|
function stub(method) {
|
|
218
219
|
return _wrapInternalErr(function () {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
var data = { shim: shim, method: method, args: args, ts: new Date() };
|
|
220
|
+
const args = Array.prototype.slice.call(arguments, 0);
|
|
221
|
+
const data = { shim: this, method: method, args: args, ts: new Date() };
|
|
222
222
|
window._rollbarShims[this.shimId()].messages.push(data);
|
|
223
223
|
});
|
|
224
224
|
}
|
|
@@ -228,8 +228,8 @@ var _methods =
|
|
|
228
228
|
',',
|
|
229
229
|
);
|
|
230
230
|
|
|
231
|
-
for (
|
|
232
|
-
Shim.prototype[
|
|
231
|
+
for (const method of _methods) {
|
|
232
|
+
Shim.prototype[method] = stub(method);
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
export { setupShim, Rollbar };
|