@newrelic/browser-agent 1.258.2 → 1.260.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/CHANGELOG.md +20 -0
- package/dist/cjs/cdn/polyfills.js +3 -1
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/harvest/harvest-scheduler.js +4 -2
- package/dist/cjs/common/session/session-entity.js +8 -1
- package/dist/cjs/common/timing/time-keeper.js +9 -30
- package/dist/cjs/features/ajax/constants.js +3 -2
- package/dist/cjs/features/jserrors/instrument/index.js +3 -4
- package/dist/cjs/features/metrics/aggregate/index.js +0 -8
- package/dist/cjs/features/page_view_event/aggregate/index.js +8 -6
- package/dist/cjs/features/session_replay/aggregate/index.js +31 -36
- package/dist/cjs/features/session_replay/constants.js +5 -2
- package/dist/cjs/features/session_replay/instrument/index.js +53 -13
- package/dist/cjs/features/session_replay/shared/recorder.js +8 -1
- package/dist/cjs/features/session_replay/shared/utils.js +3 -5
- package/dist/cjs/features/session_trace/aggregate/index.js +181 -527
- package/dist/cjs/features/session_trace/aggregate/trace/node.js +19 -0
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +289 -0
- package/dist/cjs/features/session_trace/constants.js +3 -2
- package/dist/cjs/features/session_trace/instrument/index.js +7 -3
- package/dist/cjs/features/utils/aggregate-base.js +1 -0
- package/dist/cjs/features/utils/feature-gates.js +17 -0
- package/dist/cjs/features/utils/instrument-base.js +2 -1
- package/dist/cjs/loaders/agent-base.js +4 -0
- package/dist/cjs/loaders/api/api-methods.js +1 -1
- package/dist/cjs/loaders/api/api.js +2 -2
- package/dist/cjs/loaders/configure/configure.js +1 -0
- package/dist/esm/cdn/polyfills.js +3 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +4 -2
- package/dist/esm/common/session/session-entity.js +8 -1
- package/dist/esm/common/timing/time-keeper.js +9 -30
- package/dist/esm/features/ajax/constants.js +2 -1
- package/dist/esm/features/jserrors/instrument/index.js +3 -4
- package/dist/esm/features/metrics/aggregate/index.js +0 -8
- package/dist/esm/features/page_view_event/aggregate/index.js +8 -6
- package/dist/esm/features/session_replay/aggregate/index.js +32 -37
- package/dist/esm/features/session_replay/constants.js +4 -1
- package/dist/esm/features/session_replay/instrument/index.js +54 -14
- package/dist/esm/features/session_replay/shared/recorder.js +8 -1
- package/dist/esm/features/session_replay/shared/utils.js +4 -6
- package/dist/esm/features/session_trace/aggregate/index.js +182 -527
- package/dist/esm/features/session_trace/aggregate/trace/node.js +12 -0
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +282 -0
- package/dist/esm/features/session_trace/constants.js +2 -1
- package/dist/esm/features/session_trace/instrument/index.js +7 -3
- package/dist/esm/features/utils/aggregate-base.js +1 -0
- package/dist/esm/features/utils/feature-gates.js +11 -0
- package/dist/esm/features/utils/instrument-base.js +3 -2
- package/dist/esm/loaders/agent-base.js +4 -0
- package/dist/esm/loaders/api/api-methods.js +1 -1
- package/dist/esm/loaders/api/api.js +2 -2
- package/dist/esm/loaders/configure/configure.js +1 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts +1 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts +2 -0
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
- package/dist/types/features/ajax/constants.d.ts +1 -0
- package/dist/types/features/ajax/constants.d.ts.map +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -0
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/constants.d.ts +3 -0
- package/dist/types/features/session_replay/instrument/index.d.ts +0 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +39 -52
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/node.d.ts +12 -0
- package/dist/types/features/session_trace/aggregate/trace/node.d.ts.map +1 -0
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +43 -0
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -0
- package/dist/types/features/session_trace/constants.d.ts +1 -0
- package/dist/types/features/session_trace/constants.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +1 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/feature-gates.d.ts +2 -0
- package/dist/types/features/utils/feature-gates.d.ts.map +1 -0
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +1 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdn/polyfills.js +2 -0
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvest-scheduler.js +4 -2
- package/src/common/session/session-entity.js +3 -1
- package/src/common/timing/time-keeper.js +9 -30
- package/src/features/ajax/constants.js +2 -0
- package/src/features/jserrors/instrument/index.js +3 -4
- package/src/features/metrics/aggregate/index.js +0 -8
- package/src/features/page_view_event/aggregate/index.js +9 -5
- package/src/features/session_replay/aggregate/index.js +30 -39
- package/src/features/session_replay/constants.js +4 -0
- package/src/features/session_replay/instrument/index.js +48 -8
- package/src/features/session_replay/shared/__mocks__/utils.js +0 -1
- package/src/features/session_replay/shared/recorder.js +8 -1
- package/src/features/session_replay/shared/utils.js +4 -7
- package/src/features/session_trace/aggregate/index.js +157 -493
- package/src/features/session_trace/aggregate/trace/node.js +12 -0
- package/src/features/session_trace/aggregate/trace/storage.js +287 -0
- package/src/features/session_trace/constants.js +1 -0
- package/src/features/session_trace/instrument/index.js +7 -2
- package/src/features/utils/__mocks__/feature-gates.js +1 -0
- package/src/features/utils/aggregate-base.js +1 -0
- package/src/features/utils/feature-gates.js +11 -0
- package/src/features/utils/instrument-base.js +3 -2
- package/src/loaders/agent-base.js +4 -0
- package/src/loaders/api/api-methods.js +1 -1
- package/src/loaders/api/api.js +2 -2
- package/src/loaders/configure/configure.js +1 -0
- package/dist/cjs/features/session_replay/shared/replay-mode.js +0 -28
- package/dist/cjs/features/utils/handler-cache.js +0 -70
- package/dist/esm/features/session_replay/shared/replay-mode.js +0 -23
- package/dist/esm/features/utils/handler-cache.js +0 -63
- package/dist/types/features/session_replay/shared/replay-mode.d.ts +0 -9
- package/dist/types/features/session_replay/shared/replay-mode.d.ts.map +0 -1
- package/dist/types/features/utils/handler-cache.d.ts +0 -23
- package/dist/types/features/utils/handler-cache.d.ts.map +0 -1
- package/src/features/session_replay/shared/replay-mode.js +0 -23
- package/src/features/utils/handler-cache.js +0 -65
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TraceNode = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* All nodes reported to the consumer must take this shape
|
|
9
|
+
*/
|
|
10
|
+
class TraceNode {
|
|
11
|
+
constructor(name, start, end, origin, type) {
|
|
12
|
+
this.n = name;
|
|
13
|
+
this.s = start;
|
|
14
|
+
this.e = end;
|
|
15
|
+
this.o = origin;
|
|
16
|
+
this.t = type;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.TraceNode = TraceNode;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TraceStorage = void 0;
|
|
7
|
+
var _runtime = require("../../../../common/constants/runtime");
|
|
8
|
+
var _constants = require("../../../../common/session/constants");
|
|
9
|
+
var _now = require("../../../../common/timing/now");
|
|
10
|
+
var _parseUrl = require("../../../../common/url/parse-url");
|
|
11
|
+
var _constants2 = require("../../constants");
|
|
12
|
+
var _node = require("./node");
|
|
13
|
+
const ERROR_MODE_SECONDS_WINDOW = 30 * 1000; // sliding window of nodes to track when simply monitoring (but not harvesting) in error mode
|
|
14
|
+
const SUPPORTS_PERFORMANCE_OBSERVER = typeof _runtime.globalScope.PerformanceObserver === 'function';
|
|
15
|
+
const ignoredEvents = {
|
|
16
|
+
// we find that certain events make the data too noisy to be useful
|
|
17
|
+
global: {
|
|
18
|
+
mouseup: true,
|
|
19
|
+
mousedown: true
|
|
20
|
+
},
|
|
21
|
+
// certain events are present both in the window and in PVT metrics. PVT metrics are prefered so the window events should be ignored
|
|
22
|
+
window: {
|
|
23
|
+
load: true,
|
|
24
|
+
pagehide: true
|
|
25
|
+
},
|
|
26
|
+
// when ajax instrumentation is disabled, all XMLHttpRequest events will return with origin = xhrOriginMissing and should be ignored
|
|
27
|
+
xhrOriginMissing: {
|
|
28
|
+
ignoreAll: true
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const toAggregate = {
|
|
32
|
+
typing: [1000, 2000],
|
|
33
|
+
scrolling: [100, 1000],
|
|
34
|
+
mousing: [1000, 2000],
|
|
35
|
+
touching: [1000, 2000]
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** The purpose of this class is to manage, normalize, and retrieve ST nodes as needed without polluting the main ST modules */
|
|
39
|
+
class TraceStorage {
|
|
40
|
+
nodeCount = 0;
|
|
41
|
+
trace = {};
|
|
42
|
+
earliestTimeStamp = Infinity;
|
|
43
|
+
latestTimeStamp = 0;
|
|
44
|
+
tempStorage = [];
|
|
45
|
+
prevStoredEvents = new Set();
|
|
46
|
+
constructor(parent) {
|
|
47
|
+
this.parent = parent;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Central function called by all the other store__ & addToTrace API to append a trace node. */
|
|
51
|
+
storeSTN(stn) {
|
|
52
|
+
if (this.parent.blocked) return;
|
|
53
|
+
if (this.nodeCount >= _constants2.MAX_NODES_PER_HARVEST) {
|
|
54
|
+
// limit the amount of pending data awaiting next harvest
|
|
55
|
+
if (this.parent.agentRuntime.session.state.sessionTraceMode !== _constants.MODE.ERROR) return;
|
|
56
|
+
const openedSpace = this.trimSTNs(ERROR_MODE_SECONDS_WINDOW); // but maybe we could make some space by discarding irrelevant nodes if we're in sessioned Error mode
|
|
57
|
+
if (openedSpace === 0) return;
|
|
58
|
+
}
|
|
59
|
+
while (this.tempStorage.length) {
|
|
60
|
+
this.storeSTN(this.tempStorage.shift());
|
|
61
|
+
}
|
|
62
|
+
if (this.trace[stn.n]) this.trace[stn.n].push(stn);else this.trace[stn.n] = [stn];
|
|
63
|
+
if (stn.s < this.earliestTimeStamp) this.earliestTimeStamp = stn.s;
|
|
64
|
+
if (stn.s > this.latestTimeStamp) this.latestTimeStamp = stn.s;
|
|
65
|
+
this.nodeCount++;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Trim the collection of nodes awaiting harvest such that those seen outside a certain span of time are discarded.
|
|
70
|
+
* @param {number} lookbackDuration Past length of time until now for which we care about nodes, in milliseconds
|
|
71
|
+
* @returns {number} However many nodes were discarded after trimming.
|
|
72
|
+
*/
|
|
73
|
+
trimSTNs(lookbackDuration) {
|
|
74
|
+
let prunedNodes = 0;
|
|
75
|
+
const cutoffHighResTime = Math.max((0, _now.now)() - lookbackDuration, 0);
|
|
76
|
+
Object.keys(this.trace).forEach(nameCategory => {
|
|
77
|
+
const nodeList = this.trace[nameCategory];
|
|
78
|
+
/* Notice nodes are appending under their name's list as they end and are stored. This means each list is already (roughly) sorted in chronological order by end time.
|
|
79
|
+
* This isn't exact since nodes go through some processing & EE handlers chain, but it's close enough as we still capture nodes whose duration overlaps the lookback window.
|
|
80
|
+
* ASSUMPTION: all 'end' timings stored are relative to timeOrigin (DOMHighResTimeStamp) and not Unix epoch based. */
|
|
81
|
+
let cutoffIdx = nodeList.findIndex(node => cutoffHighResTime <= node.e);
|
|
82
|
+
if (cutoffIdx === 0) return;else if (cutoffIdx < 0) {
|
|
83
|
+
// whole list falls outside lookback window and is irrelevant
|
|
84
|
+
cutoffIdx = nodeList.length;
|
|
85
|
+
delete this.trace[nameCategory];
|
|
86
|
+
} else nodeList.splice(0, cutoffIdx); // chop off everything outside our window i.e. before the last <lookbackDuration> timeframe
|
|
87
|
+
|
|
88
|
+
this.nodeCount -= cutoffIdx;
|
|
89
|
+
prunedNodes += cutoffIdx;
|
|
90
|
+
});
|
|
91
|
+
return prunedNodes;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Used by session trace's harvester to create the payload body. */
|
|
95
|
+
takeSTNs() {
|
|
96
|
+
if (!SUPPORTS_PERFORMANCE_OBSERVER) {
|
|
97
|
+
// if PO isn't supported, this checks resourcetiming buffer every harvest.
|
|
98
|
+
this.storeResources(_runtime.globalScope.performance?.getEntriesByType?.('resource'));
|
|
99
|
+
}
|
|
100
|
+
const stns = Object.entries(this.trace).flatMap(_ref => {
|
|
101
|
+
let [name, listOfSTNodes] = _ref;
|
|
102
|
+
// basically take the "this.trace" map-obj and concat all the list-type values
|
|
103
|
+
if (!(name in toAggregate)) return listOfSTNodes;
|
|
104
|
+
// Special processing for event nodes dealing with user inputs:
|
|
105
|
+
const reindexByOriginFn = this.smearEvtsByOrigin(name);
|
|
106
|
+
const partitionListByOriginMap = listOfSTNodes.sort((a, b) => a.s - b.s).reduce(reindexByOriginFn, {});
|
|
107
|
+
return Object.values(partitionListByOriginMap).flat(); // join the partitions back into 1-D, now ordered by origin then start time
|
|
108
|
+
}, this);
|
|
109
|
+
if (stns.length === 0) return {};
|
|
110
|
+
this.trace = {};
|
|
111
|
+
this.nodeCount = 0;
|
|
112
|
+
const earliestTimeStamp = this.earliestTimeStamp;
|
|
113
|
+
this.earliestTimeStamp = Infinity;
|
|
114
|
+
const latestTimeStamp = this.latestTimeStamp;
|
|
115
|
+
this.latestTimeStamp = 0;
|
|
116
|
+
return {
|
|
117
|
+
stns,
|
|
118
|
+
earliestTimeStamp,
|
|
119
|
+
latestTimeStamp
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
smearEvtsByOrigin(name) {
|
|
123
|
+
const maxGap = toAggregate[name][0];
|
|
124
|
+
const maxLen = toAggregate[name][1];
|
|
125
|
+
const lastO = {};
|
|
126
|
+
return (byOrigin, evtNode) => {
|
|
127
|
+
let lastArr = byOrigin[evtNode.o];
|
|
128
|
+
if (!lastArr) lastArr = byOrigin[evtNode.o] = [];
|
|
129
|
+
const last = lastO[evtNode.o];
|
|
130
|
+
if (name === 'scrolling' && !trivial(evtNode)) {
|
|
131
|
+
lastO[evtNode.o] = null;
|
|
132
|
+
evtNode.n = 'scroll';
|
|
133
|
+
lastArr.push(evtNode);
|
|
134
|
+
} else if (last && evtNode.s - last.s < maxLen && last.e > evtNode.s - maxGap) {
|
|
135
|
+
last.e = evtNode.e;
|
|
136
|
+
} else {
|
|
137
|
+
lastO[evtNode.o] = evtNode;
|
|
138
|
+
lastArr.push(evtNode);
|
|
139
|
+
}
|
|
140
|
+
return byOrigin;
|
|
141
|
+
};
|
|
142
|
+
function trivial(node) {
|
|
143
|
+
const limit = 4;
|
|
144
|
+
return !!(node && typeof node.e === 'number' && typeof node.s === 'number' && node.e - node.s < limit);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
processPVT(name, value, attrs) {
|
|
148
|
+
this.storeTiming({
|
|
149
|
+
[name]: value
|
|
150
|
+
});
|
|
151
|
+
if (hasFID(name, attrs)) this.storeEvent({
|
|
152
|
+
type: 'fid',
|
|
153
|
+
target: 'document'
|
|
154
|
+
}, 'document', value, value + attrs.fid);
|
|
155
|
+
function hasFID(name, attrs) {
|
|
156
|
+
return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
storeTiming(timingEntry) {
|
|
160
|
+
if (!timingEntry) return;
|
|
161
|
+
|
|
162
|
+
// loop iterates through prototype also (for FF)
|
|
163
|
+
for (let key in timingEntry) {
|
|
164
|
+
let val = timingEntry[key];
|
|
165
|
+
|
|
166
|
+
// ignore size and status type nodes that do not map to timestamp metrics
|
|
167
|
+
const lck = key.toLowerCase();
|
|
168
|
+
if (lck.indexOf('size') >= 0 || lck.indexOf('status') >= 0) continue;
|
|
169
|
+
|
|
170
|
+
// ignore inherited methods, meaningless 0 values, and bogus timestamps
|
|
171
|
+
// that are in the future (Microsoft Edge seems to sometimes produce these)
|
|
172
|
+
if (!(typeof val === 'number' && val >= 0)) continue;
|
|
173
|
+
val = Math.round(val);
|
|
174
|
+
this.storeSTN(new _node.TraceNode(key, val, val, 'document', 'timing'));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Tracks the events and their listener's duration on objects wrapped by wrap-events.
|
|
179
|
+
storeEvent(currentEvent, target, start, end) {
|
|
180
|
+
if (this.shouldIgnoreEvent(currentEvent, target)) return;
|
|
181
|
+
if (this.prevStoredEvents.has(currentEvent)) return; // prevent multiple listeners of an event from creating duplicate trace nodes per occurrence. Cleared every harvest. near-zero chance for re-duplication after clearing per harvest since the timestamps of the event are considered for uniqueness.
|
|
182
|
+
this.prevStoredEvents.add(currentEvent);
|
|
183
|
+
const evt = new _node.TraceNode(this.evtName(currentEvent.type), start, end, undefined, 'event');
|
|
184
|
+
try {
|
|
185
|
+
// webcomponents-lite.js can trigger an exception on currentEvent.target getter because
|
|
186
|
+
// it does not check currentEvent.currentTarget before calling getRootNode() on it
|
|
187
|
+
evt.o = this.evtOrigin(currentEvent.target, target);
|
|
188
|
+
} catch (e) {
|
|
189
|
+
evt.o = this.evtOrigin(null, target);
|
|
190
|
+
}
|
|
191
|
+
this.storeSTN(evt);
|
|
192
|
+
}
|
|
193
|
+
shouldIgnoreEvent(event, target) {
|
|
194
|
+
const origin = this.evtOrigin(event.target, target);
|
|
195
|
+
if (event.type in ignoredEvents.global) return true;
|
|
196
|
+
if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true;
|
|
197
|
+
return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin]);
|
|
198
|
+
}
|
|
199
|
+
evtName(type) {
|
|
200
|
+
switch (type) {
|
|
201
|
+
case 'keydown':
|
|
202
|
+
case 'keyup':
|
|
203
|
+
case 'keypress':
|
|
204
|
+
return 'typing';
|
|
205
|
+
case 'mousemove':
|
|
206
|
+
case 'mouseenter':
|
|
207
|
+
case 'mouseleave':
|
|
208
|
+
case 'mouseover':
|
|
209
|
+
case 'mouseout':
|
|
210
|
+
return 'mousing';
|
|
211
|
+
case 'scroll':
|
|
212
|
+
return 'scrolling';
|
|
213
|
+
case 'touchstart':
|
|
214
|
+
case 'touchmove':
|
|
215
|
+
case 'touchend':
|
|
216
|
+
case 'touchcancel':
|
|
217
|
+
case 'touchenter':
|
|
218
|
+
case 'touchleave':
|
|
219
|
+
return 'touching';
|
|
220
|
+
default:
|
|
221
|
+
return type;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
evtOrigin(t, target) {
|
|
225
|
+
let origin = 'unknown';
|
|
226
|
+
if (t && t instanceof XMLHttpRequest) {
|
|
227
|
+
const params = this.parent.ee.context(t).params;
|
|
228
|
+
if (!params || !params.status || !params.method || !params.host || !params.pathname) return 'xhrOriginMissing';
|
|
229
|
+
origin = params.status + ' ' + params.method + ': ' + params.host + params.pathname;
|
|
230
|
+
} else if (t && typeof t.tagName === 'string') {
|
|
231
|
+
origin = t.tagName.toLowerCase();
|
|
232
|
+
if (t.id) origin += '#' + t.id;
|
|
233
|
+
if (t.className) {
|
|
234
|
+
for (let i = 0; i < t.classList.length; i++) origin += '.' + t.classList[i];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (origin === 'unknown') {
|
|
238
|
+
if (typeof target === 'string') origin = target;else if (target === document) origin = 'document';else if (target === window) origin = 'window';else if (target instanceof FileReader) origin = 'FileReader';
|
|
239
|
+
}
|
|
240
|
+
return origin;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Tracks when the window history API specified by wrap-history is used.
|
|
244
|
+
storeHist(path, old, time) {
|
|
245
|
+
this.storeSTN(new _node.TraceNode('history.pushState', time, time, path, old));
|
|
246
|
+
}
|
|
247
|
+
#laststart = 0;
|
|
248
|
+
// Processes all the PerformanceResourceTiming entries captured (by observer).
|
|
249
|
+
storeResources(resources) {
|
|
250
|
+
if (!resources || resources.length === 0) return;
|
|
251
|
+
resources.forEach(currentResource => {
|
|
252
|
+
if ((currentResource.fetchStart | 0) <= this.#laststart) return; // don't recollect already-seen resources
|
|
253
|
+
|
|
254
|
+
const {
|
|
255
|
+
initiatorType,
|
|
256
|
+
fetchStart,
|
|
257
|
+
responseEnd,
|
|
258
|
+
entryType
|
|
259
|
+
} = currentResource;
|
|
260
|
+
const {
|
|
261
|
+
protocol,
|
|
262
|
+
hostname,
|
|
263
|
+
port,
|
|
264
|
+
pathname
|
|
265
|
+
} = (0, _parseUrl.parseUrl)(currentResource.name);
|
|
266
|
+
const res = new _node.TraceNode(initiatorType, fetchStart | 0, responseEnd | 0, "".concat(protocol, "://").concat(hostname, ":").concat(port).concat(pathname), entryType);
|
|
267
|
+
this.storeSTN(res);
|
|
268
|
+
});
|
|
269
|
+
this.#laststart = resources[resources.length - 1].fetchStart | 0;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// JavascriptError (FEATURE) events pipes into ST here.
|
|
273
|
+
storeErrorAgg(type, name, params, metrics) {
|
|
274
|
+
if (type !== 'err') return; // internal errors are purposefully ignored
|
|
275
|
+
this.storeSTN(new _node.TraceNode('error', metrics.time, metrics.time, params.message, params.stackHash));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Ajax (FEATURE) events--XML & fetches--pipes into ST here.
|
|
279
|
+
storeXhrAgg(type, name, params, metrics) {
|
|
280
|
+
if (type !== 'xhr') return;
|
|
281
|
+
this.storeSTN(new _node.TraceNode('Ajax', metrics.time, metrics.time + metrics.duration, "".concat(params.status, " ").concat(params.method, ": ").concat(params.host).concat(params.pathname)));
|
|
282
|
+
}
|
|
283
|
+
restoreNode(name, listOfSTNodes) {
|
|
284
|
+
if (this.nodeCount >= _constants2.MAX_NODES_PER_HARVEST) return;
|
|
285
|
+
this.nodeCount += listOfSTNodes.length;
|
|
286
|
+
this.trace[name] = this.trace[name] ? listOfSTNodes.concat(this.trace[name]) : listOfSTNodes;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
exports.TraceStorage = TraceStorage;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.START = exports.RESOURCE = exports.PUSH_STATE = exports.FN_START = exports.FN_END = exports.FEATURE_NAME = exports.END = exports.BST_RESOURCE = void 0;
|
|
6
|
+
exports.START = exports.RESOURCE = exports.PUSH_STATE = exports.MAX_NODES_PER_HARVEST = exports.FN_START = exports.FN_END = exports.FEATURE_NAME = exports.END = exports.BST_RESOURCE = void 0;
|
|
7
7
|
var _features = require("../../loaders/features/features");
|
|
8
8
|
const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.sessionTrace;
|
|
9
9
|
const BST_RESOURCE = exports.BST_RESOURCE = 'bstResource';
|
|
@@ -12,4 +12,5 @@ const START = exports.START = '-start';
|
|
|
12
12
|
const END = exports.END = '-end';
|
|
13
13
|
const FN_START = exports.FN_START = 'fn' + START;
|
|
14
14
|
const FN_END = exports.FN_END = 'fn' + END;
|
|
15
|
-
const PUSH_STATE = exports.PUSH_STATE = 'pushState';
|
|
15
|
+
const PUSH_STATE = exports.PUSH_STATE = 'pushState';
|
|
16
|
+
const MAX_NODES_PER_HARVEST = exports.MAX_NODES_PER_HARVEST = 1000;
|
|
@@ -9,7 +9,8 @@ var _wrap = require("../../../common/wrap");
|
|
|
9
9
|
var _instrumentBase = require("../../utils/instrument-base");
|
|
10
10
|
var CONSTANTS = _interopRequireWildcard(require("../constants"));
|
|
11
11
|
var _features = require("../../../loaders/features/features");
|
|
12
|
-
var
|
|
12
|
+
var _drain = require("../../../common/drain/drain");
|
|
13
|
+
var _featureGates = require("../../utils/feature-gates");
|
|
13
14
|
var _now = require("../../../common/timing/now");
|
|
14
15
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
15
16
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -33,8 +34,11 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
33
34
|
constructor(agentIdentifier, aggregator) {
|
|
34
35
|
let auto = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
35
36
|
super(agentIdentifier, aggregator, FEATURE_NAME, auto);
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const canTrackSession = (0, _featureGates.canEnableSessionTracking)(this.agentIdentifier);
|
|
38
|
+
if (!canTrackSession) {
|
|
39
|
+
(0, _drain.deregisterDrain)(this.agentIdentifier, this.featureName);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
38
42
|
const thisInstrumentEE = this.ee;
|
|
39
43
|
(0, _wrap.wrapHistory)(thisInstrumentEE);
|
|
40
44
|
this.eventsEE = (0, _wrap.wrapEvents)(thisInstrumentEE);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.canEnableSessionTracking = void 0;
|
|
7
|
+
var _config = require("../../common/config/config");
|
|
8
|
+
var _runtime = require("../../common/constants/runtime");
|
|
9
|
+
/**
|
|
10
|
+
* Checks if session can be tracked, affects session entity and dependent features
|
|
11
|
+
* @param {string} agentId
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
const canEnableSessionTracking = agentId => {
|
|
15
|
+
return _runtime.isBrowserScope && (0, _config.getConfigurationValue)(agentId, 'privacy.cookies_enabled') === true;
|
|
16
|
+
};
|
|
17
|
+
exports.canEnableSessionTracking = canEnableSessionTracking;
|
|
@@ -12,6 +12,7 @@ var _console = require("../../common/util/console");
|
|
|
12
12
|
var _features = require("../../loaders/features/features");
|
|
13
13
|
var _config = require("../../common/config/config");
|
|
14
14
|
var _utils = require("../session_replay/shared/utils");
|
|
15
|
+
var _featureGates = require("./feature-gates");
|
|
15
16
|
var _invoke = require("../../common/util/invoke");
|
|
16
17
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
17
18
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /**
|
|
@@ -83,7 +84,7 @@ class InstrumentBase extends _featureBase.FeatureBase {
|
|
|
83
84
|
const importLater = async () => {
|
|
84
85
|
let session;
|
|
85
86
|
try {
|
|
86
|
-
if ((0,
|
|
87
|
+
if ((0, _featureGates.canEnableSessionTracking)(this.agentIdentifier)) {
|
|
87
88
|
// would require some setup before certain features start
|
|
88
89
|
const {
|
|
89
90
|
setupAgentSession
|
|
@@ -7,6 +7,7 @@ exports.AgentBase = void 0;
|
|
|
7
7
|
var _console = require("../common/util/console");
|
|
8
8
|
var _constants = require("../features/session_replay/constants");
|
|
9
9
|
var _uniqueId = require("../common/ids/unique-id");
|
|
10
|
+
var _contextualEe = require("../common/event-emitter/contextual-ee");
|
|
10
11
|
/* eslint-disable n/handle-callback-err */
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -18,6 +19,9 @@ class AgentBase {
|
|
|
18
19
|
constructor() {
|
|
19
20
|
let agentIdentifier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (0, _uniqueId.generateRandomHexString)(16);
|
|
20
21
|
this.agentIdentifier = agentIdentifier;
|
|
22
|
+
|
|
23
|
+
// Assign the observation context to the event emitter, so it knows how to create observation contexts
|
|
24
|
+
this.ee = _contextualEe.ee.get(agentIdentifier);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
/**
|
|
@@ -5,5 +5,5 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.asyncApiMethods = exports.apiMethods = void 0;
|
|
7
7
|
var _constants = require("../../features/session_replay/constants");
|
|
8
|
-
const apiMethods = exports.apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start',
|
|
8
|
+
const apiMethods = exports.apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', _constants.SR_EVENT_EMITTER_TYPES.RECORD, _constants.SR_EVENT_EMITTER_TYPES.PAUSE];
|
|
9
9
|
const asyncApiMethods = exports.asyncApiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];
|
|
@@ -206,8 +206,8 @@ function setAPI(agentIdentifier, forceDrain) {
|
|
|
206
206
|
} = _ref;
|
|
207
207
|
setAPI(agentIdentifier);
|
|
208
208
|
(0, _drain.drain)(agentIdentifier, 'api');
|
|
209
|
-
}).catch(
|
|
210
|
-
(0, _console.warn)('Downloading runtime APIs failed...');
|
|
209
|
+
}).catch(err => {
|
|
210
|
+
(0, _console.warn)('Downloading runtime APIs failed...', err);
|
|
211
211
|
instanceEE.abort();
|
|
212
212
|
});
|
|
213
213
|
}
|
|
@@ -60,6 +60,7 @@ function configure(agent) {
|
|
|
60
60
|
agent.runSoftNavOverSpa &&= updatedInit.soft_navigations.enabled === true && updatedInit.feature_flags.includes('soft_nav');
|
|
61
61
|
}
|
|
62
62
|
runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
|
|
63
|
+
runtime.ptid = agent.agentIdentifier;
|
|
63
64
|
(0, _config.setRuntime)(agent.agentIdentifier, runtime);
|
|
64
65
|
if (agent.api === undefined) agent.api = (0, _api.setAPI)(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
|
|
65
66
|
if (agent.exposed === undefined) agent.exposed = exposed;
|
|
@@ -10,6 +10,7 @@ import 'core-js/stable/array/flat';
|
|
|
10
10
|
import 'core-js/stable/array/flat-map';
|
|
11
11
|
import 'core-js/stable/array/from';
|
|
12
12
|
import 'core-js/stable/array/some';
|
|
13
|
+
import 'core-js/stable/array/find-index';
|
|
13
14
|
import 'core-js/stable/object/assign';
|
|
14
15
|
import 'core-js/stable/object/entries';
|
|
15
16
|
import 'core-js/stable/object/values';
|
|
@@ -22,4 +23,5 @@ import 'core-js/stable/object/get-own-property-descriptors';
|
|
|
22
23
|
import 'core-js/stable/url';
|
|
23
24
|
import 'core-js/stable/url-search-params';
|
|
24
25
|
import 'core-js/stable/string/starts-with';
|
|
25
|
-
import 'core-js/stable/number/is-nan';
|
|
26
|
+
import 'core-js/stable/number/is-nan';
|
|
27
|
+
import 'core-js/stable/string/includes';
|
|
@@ -75,7 +75,7 @@ export function drain() {
|
|
|
75
75
|
function checkCanDrainAll(agentIdentifier) {
|
|
76
76
|
// Only when the event-groups for all features are ready to drain (staged) do we execute the drain. This has the effect
|
|
77
77
|
// that the last feature to call drain triggers drain for all features.
|
|
78
|
-
const items =
|
|
78
|
+
const items = Array.from(registry[agentIdentifier]);
|
|
79
79
|
if (items.every(_ref => {
|
|
80
80
|
let [key, values] = _ref;
|
|
81
81
|
return values.staged;
|
|
@@ -31,7 +31,7 @@ export class HarvestScheduler extends SharedContext {
|
|
|
31
31
|
this.started = false;
|
|
32
32
|
this.timeoutHandle = null;
|
|
33
33
|
this.aborted = false; // this controls the per-interval and final harvests for the scheduler (currently per feature specific!)
|
|
34
|
-
|
|
34
|
+
this.harvesting = false;
|
|
35
35
|
this.harvest = new Harvest(this.sharedContext);
|
|
36
36
|
|
|
37
37
|
// unload if EOL mechanism fires
|
|
@@ -82,12 +82,14 @@ export class HarvestScheduler extends SharedContext {
|
|
|
82
82
|
}
|
|
83
83
|
runHarvest(opts) {
|
|
84
84
|
if (this.aborted) return;
|
|
85
|
+
this.harvesting = true;
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
|
|
88
89
|
* @param {Object} result
|
|
89
90
|
*/
|
|
90
91
|
const cbRanAfterSend = result => {
|
|
92
|
+
this.harvesting = false;
|
|
91
93
|
if (opts?.forceNoRetry) result.retry = false; // discard unsent data rather than re-queuing for next harvest attempt
|
|
92
94
|
this.onHarvestFinished(opts, result);
|
|
93
95
|
};
|
|
@@ -103,7 +105,7 @@ export class HarvestScheduler extends SharedContext {
|
|
|
103
105
|
const retry = !opts?.unload && submitMethod === submitData.xhr;
|
|
104
106
|
payload = this.opts.getPayload({
|
|
105
107
|
retry,
|
|
106
|
-
opts
|
|
108
|
+
...opts
|
|
107
109
|
});
|
|
108
110
|
if (!payload) {
|
|
109
111
|
if (this.started) {
|
|
@@ -69,8 +69,15 @@ export class SessionEntity {
|
|
|
69
69
|
expiresMs = DEFAULT_EXPIRES_MS,
|
|
70
70
|
inactiveMs = DEFAULT_INACTIVE_MS
|
|
71
71
|
} = _ref;
|
|
72
|
+
/** Ensure that certain properties are preserved across a reset if already set */
|
|
73
|
+
const persistentAttributes = {
|
|
74
|
+
serverTimeDiff: this.state.serverTimeDiff || model.serverTimeDiff
|
|
75
|
+
};
|
|
72
76
|
this.state = {};
|
|
73
|
-
this.sync(
|
|
77
|
+
this.sync({
|
|
78
|
+
...model,
|
|
79
|
+
...persistentAttributes
|
|
80
|
+
});
|
|
74
81
|
|
|
75
82
|
// value is intended to act as the primary value of the k=v pair
|
|
76
83
|
this.state.value = value;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { originTime } from '../constants/runtime';
|
|
2
|
-
import { ee as baseEE } from '../event-emitter/contextual-ee';
|
|
3
2
|
import { getRuntime } from '../config/config';
|
|
4
|
-
import { SESSION_EVENT_TYPES, SESSION_EVENTS } from '../session/constants';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Class used to adjust the timestamp of harvested data to New Relic server time. This
|
|
@@ -36,18 +34,7 @@ export class TimeKeeper {
|
|
|
36
34
|
#ready = false;
|
|
37
35
|
constructor(agentIdentifier) {
|
|
38
36
|
this.#session = getRuntime(agentIdentifier)?.session;
|
|
39
|
-
|
|
40
|
-
const ee = baseEE.get(agentIdentifier);
|
|
41
|
-
ee.on(SESSION_EVENTS.UPDATE, this.#processSessionUpdate.bind(this));
|
|
42
|
-
ee.on(SESSION_EVENTS.STARTED, () => {
|
|
43
|
-
if (this.#ready) {
|
|
44
|
-
this.#session.write({
|
|
45
|
-
serverTimeDiff: this.#localTimeDiff
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
this.#processSessionUpdate(null, this.#session.read());
|
|
50
|
-
}
|
|
37
|
+
this.processStoredDiff();
|
|
51
38
|
}
|
|
52
39
|
get ready() {
|
|
53
40
|
return this.#ready;
|
|
@@ -63,8 +50,8 @@ export class TimeKeeper {
|
|
|
63
50
|
* @param endTime {number} The end time of the RUM request
|
|
64
51
|
*/
|
|
65
52
|
processRumRequest(rumRequest, startTime, endTime) {
|
|
53
|
+
this.processStoredDiff();
|
|
66
54
|
if (this.#ready) return; // Server time calculated from session entity
|
|
67
|
-
|
|
68
55
|
const responseDateHeader = rumRequest.getResponseHeader('Date');
|
|
69
56
|
if (!responseDateHeader) {
|
|
70
57
|
throw new Error('Missing date header on rum response.');
|
|
@@ -75,10 +62,10 @@ export class TimeKeeper {
|
|
|
75
62
|
// Corrected page origin time
|
|
76
63
|
this.#correctedOriginTime = Math.floor(Date.parse(responseDateHeader) - serverOffset);
|
|
77
64
|
this.#localTimeDiff = originTime - this.#correctedOriginTime;
|
|
78
|
-
if (
|
|
65
|
+
if (isNaN(this.#correctedOriginTime)) {
|
|
79
66
|
throw new Error('Date header invalid format.');
|
|
80
67
|
}
|
|
81
|
-
|
|
68
|
+
this.#session?.write({
|
|
82
69
|
serverTimeDiff: this.#localTimeDiff
|
|
83
70
|
});
|
|
84
71
|
this.#ready = true;
|
|
@@ -103,19 +90,11 @@ export class TimeKeeper {
|
|
|
103
90
|
return Math.floor(timestamp - this.#localTimeDiff);
|
|
104
91
|
}
|
|
105
92
|
|
|
106
|
-
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
#processSessionUpdate(type, data) {
|
|
112
|
-
if (typeof data?.serverTimeDiff !== 'number') return;
|
|
113
|
-
if (!type && !this.#ready ||
|
|
114
|
-
// This captures the initial read from the session entity when the timekeeper first initializes
|
|
115
|
-
type === SESSION_EVENT_TYPES.CROSS_TAB // This captures any cross-tab write of the session entity
|
|
116
|
-
) {
|
|
117
|
-
// This captures the initial read from the session entity when the timekeeper first initializes
|
|
118
|
-
this.#localTimeDiff = data.serverTimeDiff;
|
|
93
|
+
/** Process the session entity and use the info to set the main time calculations if present */
|
|
94
|
+
processStoredDiff() {
|
|
95
|
+
const storedServerTimeDiff = this.#session?.read()?.serverTimeDiff;
|
|
96
|
+
if (typeof storedServerTimeDiff === 'number' && !isNaN(storedServerTimeDiff)) {
|
|
97
|
+
this.#localTimeDiff = storedServerTimeDiff;
|
|
119
98
|
this.#correctedOriginTime = originTime - this.#localTimeDiff;
|
|
120
99
|
this.#ready = true;
|
|
121
100
|
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import { handle } from '../../../common/event-emitter/handle';
|
|
7
7
|
import { InstrumentBase } from '../../utils/instrument-base';
|
|
8
8
|
import { FEATURE_NAME } from '../constants';
|
|
9
|
-
import { FEATURE_NAMES } from '../../../loaders/features/features';
|
|
10
9
|
import { globalScope } from '../../../common/constants/runtime';
|
|
11
10
|
import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts';
|
|
12
11
|
import { now } from '../../../common/timing/now';
|
|
@@ -24,7 +23,7 @@ export class Instrument extends InstrumentBase {
|
|
|
24
23
|
} catch (e) {}
|
|
25
24
|
this.ee.on('internal-error', error => {
|
|
26
25
|
if (!this.abortHandler) return;
|
|
27
|
-
handle('ierr', [castError(error), now(), true, {}, this.#replayRunning], undefined,
|
|
26
|
+
handle('ierr', [castError(error), now(), true, {}, this.#replayRunning], undefined, this.featureName, this.ee);
|
|
28
27
|
});
|
|
29
28
|
this.ee.on(SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, isRunning => {
|
|
30
29
|
this.#replayRunning = isRunning;
|
|
@@ -33,11 +32,11 @@ export class Instrument extends InstrumentBase {
|
|
|
33
32
|
if (!this.abortHandler) return;
|
|
34
33
|
handle('err', [castPromiseRejectionEvent(promiseRejectionEvent), now(), false, {
|
|
35
34
|
unhandledPromiseRejection: 1
|
|
36
|
-
}, this.#replayRunning], undefined,
|
|
35
|
+
}, this.#replayRunning], undefined, this.featureName, this.ee);
|
|
37
36
|
}, eventListenerOpts(false, this.removeOnAbort?.signal));
|
|
38
37
|
globalScope.addEventListener('error', errorEvent => {
|
|
39
38
|
if (!this.abortHandler) return;
|
|
40
|
-
handle('err', [castErrorEvent(errorEvent), now(), false, {}, this.#replayRunning], undefined,
|
|
39
|
+
handle('err', [castErrorEvent(errorEvent), now(), false, {}, this.#replayRunning], undefined, this.featureName, this.ee);
|
|
41
40
|
}, eventListenerOpts(false, this.removeOnAbort?.signal));
|
|
42
41
|
this.abortHandler = this.#abort; // we also use this as a flag to denote that the feature is active or on and handling errors
|
|
43
42
|
this.importAggregator();
|