@newrelic/browser-agent 1.255.0 → 1.256.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/common/constants/env.cdn.js +2 -2
  3. package/dist/cjs/common/constants/env.npm.js +2 -2
  4. package/dist/cjs/common/constants/runtime.js +1 -1
  5. package/dist/cjs/common/harvest/harvest.js +1 -0
  6. package/dist/cjs/common/session/session-entity.js +2 -1
  7. package/dist/cjs/common/timer/interaction-timer.js +16 -2
  8. package/dist/cjs/common/timing/time-keeper.js +1 -2
  9. package/dist/cjs/features/jserrors/aggregate/index.js +16 -6
  10. package/dist/cjs/features/jserrors/instrument/index.js +8 -3
  11. package/dist/cjs/features/session_replay/aggregate/index.js +48 -29
  12. package/dist/cjs/features/session_replay/constants.js +2 -1
  13. package/dist/cjs/features/session_replay/instrument/index.js +9 -2
  14. package/dist/cjs/features/session_replay/shared/recorder-events.js +1 -9
  15. package/dist/cjs/features/session_replay/shared/recorder.js +22 -50
  16. package/dist/cjs/features/session_replay/shared/utils.js +12 -0
  17. package/dist/cjs/features/session_trace/aggregate/index.js +19 -22
  18. package/dist/cjs/loaders/api/api.js +7 -1
  19. package/dist/cjs/loaders/configure/configure.js +1 -0
  20. package/dist/esm/common/constants/env.cdn.js +2 -2
  21. package/dist/esm/common/constants/env.npm.js +2 -2
  22. package/dist/esm/common/constants/runtime.js +1 -1
  23. package/dist/esm/common/harvest/harvest.js +1 -0
  24. package/dist/esm/common/session/session-entity.js +2 -1
  25. package/dist/esm/common/timer/interaction-timer.js +16 -2
  26. package/dist/esm/common/timing/time-keeper.js +1 -3
  27. package/dist/esm/features/jserrors/aggregate/index.js +16 -6
  28. package/dist/esm/features/jserrors/instrument/index.js +8 -3
  29. package/dist/esm/features/session_replay/aggregate/index.js +48 -29
  30. package/dist/esm/features/session_replay/constants.js +2 -1
  31. package/dist/esm/features/session_replay/instrument/index.js +9 -2
  32. package/dist/esm/features/session_replay/shared/recorder-events.js +1 -9
  33. package/dist/esm/features/session_replay/shared/recorder.js +23 -51
  34. package/dist/esm/features/session_replay/shared/utils.js +11 -0
  35. package/dist/esm/features/session_trace/aggregate/index.js +19 -22
  36. package/dist/esm/loaders/api/api.js +7 -1
  37. package/dist/esm/loaders/configure/configure.js +1 -0
  38. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  39. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  40. package/dist/types/common/timer/interaction-timer.d.ts +2 -0
  41. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  42. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  43. package/dist/types/features/jserrors/aggregate/index.d.ts +2 -1
  44. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  45. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  46. package/dist/types/features/session_replay/aggregate/index.d.ts +5 -2
  47. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  48. package/dist/types/features/session_replay/constants.d.ts +1 -0
  49. package/dist/types/features/session_replay/constants.d.ts.map +1 -1
  50. package/dist/types/features/session_replay/instrument/index.d.ts +1 -0
  51. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  52. package/dist/types/features/session_replay/shared/recorder-events.d.ts +0 -8
  53. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
  54. package/dist/types/features/session_replay/shared/recorder.d.ts +1 -17
  55. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  56. package/dist/types/features/session_replay/shared/utils.d.ts +8 -0
  57. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
  58. package/dist/types/features/session_trace/aggregate/index.d.ts +2 -1
  59. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  60. package/dist/types/loaders/api/api.d.ts.map +1 -1
  61. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  62. package/package.json +2 -2
  63. package/src/common/constants/runtime.js +1 -1
  64. package/src/common/harvest/harvest.js +1 -1
  65. package/src/common/session/session-entity.js +2 -1
  66. package/src/common/timer/interaction-timer.js +17 -2
  67. package/src/common/timing/time-keeper.js +1 -3
  68. package/src/features/jserrors/aggregate/index.js +15 -6
  69. package/src/features/jserrors/instrument/index.js +9 -4
  70. package/src/features/session_replay/aggregate/index.js +43 -25
  71. package/src/features/session_replay/constants.js +2 -1
  72. package/src/features/session_replay/instrument/index.js +7 -2
  73. package/src/features/session_replay/shared/recorder-events.js +1 -6
  74. package/src/features/session_replay/shared/recorder.js +21 -27
  75. package/src/features/session_replay/shared/utils.js +12 -0
  76. package/src/features/session_trace/aggregate/index.js +18 -16
  77. package/src/loaders/api/api.js +10 -1
  78. package/src/loaders/configure/configure.js +1 -0
@@ -1,6 +1,6 @@
1
1
  import { record as recorder } from 'rrweb';
2
2
  import { stringify } from '../../../common/util/stringify';
3
- import { AVG_COMPRESSION, CHECKOUT_MS, IDEAL_PAYLOAD_SIZE, QUERY_PARAM_PADDING, RRWEB_EVENT_TYPES } from '../constants';
3
+ import { AVG_COMPRESSION, CHECKOUT_MS, IDEAL_PAYLOAD_SIZE, QUERY_PARAM_PADDING, RRWEB_EVENT_TYPES, SR_EVENT_EMITTER_TYPES } from '../constants';
4
4
  import { getConfigurationValue } from '../../../common/config/config';
5
5
  import { RecorderEvents } from './recorder-events';
6
6
  import { MODE } from '../../../common/session/constants';
@@ -8,6 +8,7 @@ import { stylesheetEvaluator } from './stylesheet-evaluator';
8
8
  import { handle } from '../../../common/event-emitter/handle';
9
9
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
10
10
  import { FEATURE_NAMES } from '../../../loaders/features/features';
11
+ import { buildNRMetaNode } from './utils';
11
12
  export class Recorder {
12
13
  /** Each page mutation or event will be stored (raw) in this array. This array will be cleared on each harvest */
13
14
  #events;
@@ -18,15 +19,9 @@ export class Recorder {
18
19
  /** flag that if true, blocks events from being "stored". Only set to true when a full snapshot has incomplete nodes (only stylesheets ATM) */
19
20
  #fixing = false;
20
21
  constructor(parent) {
21
- this.#events = new RecorderEvents({
22
- canCorrectTimestamps: !!parent.timeKeeper?.ready
23
- });
24
- this.#backloggedEvents = new RecorderEvents({
25
- canCorrectTimestamps: !!parent.timeKeeper?.ready
26
- });
27
- this.#preloaded = [new RecorderEvents({
28
- canCorrectTimestamps: !!parent.timeKeeper?.ready
29
- })];
22
+ this.#events = new RecorderEvents();
23
+ this.#backloggedEvents = new RecorderEvents();
24
+ this.#preloaded = [new RecorderEvents()];
30
25
  /** True when actively recording, false when paused or stopped */
31
26
  this.recording = false;
32
27
  /** The pointer to the current bucket holding rrweb events */
@@ -43,18 +38,12 @@ export class Recorder {
43
38
  this.stopRecording = () => {/* no-op until set by rrweb initializer */};
44
39
  }
45
40
  getEvents() {
46
- if (this.#preloaded[0]?.events.length) {
47
- const preloadedEvents = this.returnCorrectTimestamps(this.#preloaded[0]);
48
- return {
49
- ...this.#preloaded[0],
50
- events: preloadedEvents,
51
- type: 'preloaded'
52
- };
53
- }
54
- const backloggedEvents = this.returnCorrectTimestamps(this.#backloggedEvents);
55
- const events = this.returnCorrectTimestamps(this.#events);
41
+ if (this.#preloaded[0]?.events.length) return {
42
+ ...this.#preloaded[0],
43
+ type: 'preloaded'
44
+ };
56
45
  return {
57
- events: [...backloggedEvents, ...events].filter(x => x),
46
+ events: [...this.#backloggedEvents.events, ...this.#events.events].filter(x => x),
58
47
  type: 'standard',
59
48
  cycleTimestamp: Math.min(this.#backloggedEvents.cycleTimestamp, this.#events.cycleTimestamp),
60
49
  payloadBytesEstimation: this.#backloggedEvents.payloadBytesEstimation + this.#events.payloadBytesEstimation,
@@ -65,34 +54,10 @@ export class Recorder {
65
54
  };
66
55
  }
67
56
 
68
- /**
69
- * Returns time-corrected events. If the events were correctable from the beginning, this correction will have already been applied.
70
- * @param {SessionReplayEvent[]} events The array of buffered SR nodes
71
- * @returns {CorrectedSessionReplayEvent[]}
72
- */
73
- returnCorrectTimestamps(events) {
74
- if (!this.parent.timeKeeper?.ready) return events.events;
75
- return events.canCorrectTimestamps ? events.events : events.events.map(_ref => {
76
- let {
77
- __serialized,
78
- timestamp,
79
- ...e
80
- } = _ref;
81
- return {
82
- timestamp: this.parent.timeKeeper.correctAbsoluteTimestamp(timestamp),
83
- ...e
84
- };
85
- });
86
- }
87
-
88
57
  /** Clears the buffer (this.#events), and resets all payload metadata properties */
89
58
  clearBuffer() {
90
- if (this.#preloaded[0]?.events.length) this.#preloaded.shift();else if (this.parent.mode === MODE.ERROR) this.#backloggedEvents = this.#events;else this.#backloggedEvents = new RecorderEvents({
91
- canCorrectTimestamps: !!this.parent.timeKeeper?.ready
92
- });
93
- this.#events = new RecorderEvents({
94
- canCorrectTimestamps: !!this.parent.timeKeeper?.ready
95
- });
59
+ if (this.#preloaded[0]?.events.length) this.#preloaded.shift();else if (this.parent.mode === MODE.ERROR) this.#backloggedEvents = this.#events;else this.#backloggedEvents = new RecorderEvents();
60
+ this.#events = new RecorderEvents();
96
61
  }
97
62
 
98
63
  /** Begin recording using configured recording lib */
@@ -110,6 +75,10 @@ export class Recorder {
110
75
  inline_images,
111
76
  collect_fonts
112
77
  } = getConfigurationValue(this.parent.agentIdentifier, 'session_replay');
78
+ const customMasker = (text, element) => {
79
+ if (element?.type?.toLowerCase() !== 'password' && (element?.dataset.nrUnmask !== undefined || element?.classList.contains('nr-unmask'))) return text;
80
+ return '*'.repeat(text.length);
81
+ };
113
82
  // set up rrweb configurations for maximum privacy --
114
83
  // https://newrelic.atlassian.net/wiki/spaces/O11Y/pages/2792293280/2023+02+28+Browser+-+Session+Replay#Configuration-options
115
84
  const stop = recorder({
@@ -120,14 +89,18 @@ export class Recorder {
120
89
  blockSelector: block_selector,
121
90
  maskInputOptions: mask_input_options,
122
91
  maskTextSelector: mask_text_selector,
92
+ maskTextFn: customMasker,
123
93
  maskAllInputs: mask_all_inputs,
94
+ maskInputFn: customMasker,
124
95
  inlineStylesheet: inline_stylesheet,
125
96
  inlineImages: inline_images,
126
97
  collectFonts: collect_fonts,
127
98
  checkoutEveryNms: CHECKOUT_MS[this.parent.mode]
128
99
  });
100
+ this.parent.ee.emit(SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, [true, this.parent.mode]);
129
101
  this.stopRecording = () => {
130
102
  this.recording = false;
103
+ this.parent.ee.emit(SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, [false, this.parent.mode]);
131
104
  stop();
132
105
  };
133
106
  }
@@ -171,7 +144,8 @@ export class Recorder {
171
144
  if (!event) return;
172
145
  if (!this.parent.scheduler && this.#preloaded.length) this.currentBufferTarget = this.#preloaded[this.#preloaded.length - 1];else this.currentBufferTarget = this.#events;
173
146
  if (this.parent.blocked) return;
174
- if (this.currentBufferTarget.canCorrectTimestamps) {
147
+ if (this.parent.timeKeeper?.ready && !event.__newrelic) {
148
+ event.__newrelic = buildNRMetaNode(event.timestamp, this.parent.timeKeeper);
175
149
  event.timestamp = this.parent.timeKeeper.correctAbsoluteTimestamp(event.timestamp);
176
150
  }
177
151
  event.__serialized = stringify(event);
@@ -206,9 +180,7 @@ export class Recorder {
206
180
  this.parent.scheduler.runHarvest();
207
181
  } else {
208
182
  // we are still in "preload" and it triggered a "stop point". Make a new set, which will get pointed at on next cycle
209
- this.#preloaded.push(new RecorderEvents({
210
- canCorrectTimestamps: !!this.parent.timeKeeper?.ready
211
- }));
183
+ this.#preloaded.push(new RecorderEvents());
212
184
  }
213
185
  }
214
186
  }
@@ -14,4 +14,15 @@ export function isPreloadAllowed(agentId) {
14
14
  export function canImportReplayAgg(agentId, sessionMgr) {
15
15
  if (!hasReplayPrerequisite(agentId)) return false;
16
16
  return !!sessionMgr?.isNew || !!sessionMgr?.state.sessionReplayMode; // Session Replay should only try to run if already running from a previous page, or at the beginning of a session
17
+ }
18
+ export function buildNRMetaNode(timestamp, timeKeeper) {
19
+ const correctedTimestamp = timeKeeper.correctAbsoluteTimestamp(timestamp);
20
+ return {
21
+ originalTimestamp: timestamp,
22
+ correctedTimestamp,
23
+ timestampDiff: timestamp - correctedTimestamp,
24
+ timeKeeperOriginTime: timeKeeper.originTime,
25
+ timeKeeperCorrectedOriginTime: timeKeeper.correctedOriginTime,
26
+ timeKeeperDiff: Math.floor(timeKeeper.originTime - timeKeeper.correctedOriginTime)
27
+ };
17
28
  }
@@ -50,10 +50,11 @@ export class Aggregate extends AggregateBase {
50
50
  // Very unlikely, but in case the existing XMLHttpRequest.prototype object on the page couldn't be wrapped.
51
51
  if (!this.agentRuntime.xhrWrappable) return;
52
52
  this.resourceObserver = argsObj?.resourceObserver; // undefined if observer couldn't be created
53
- this.ptid = '';
53
+ this.ptid = this.agentRuntime.ptid;
54
54
  this.trace = {};
55
55
  this.nodeCount = 0;
56
56
  this.sentTrace = null;
57
+ this.everSent = false;
57
58
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10;
58
59
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000;
59
60
  /**
@@ -105,9 +106,7 @@ export class Aggregate extends AggregateBase {
105
106
  this.isStandalone = false;
106
107
  if (prevMode === MODE.ERROR && this.#scheduler) {
107
108
  this.trimSTNs(ERROR_MODE_SECONDS_WINDOW); // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
108
- this.#scheduler.runHarvest({
109
- needResponse: true
110
- });
109
+ this.#scheduler.runHarvest({});
111
110
  } else {
112
111
  controlTraceOp(MODE.FULL);
113
112
  }
@@ -130,7 +129,7 @@ export class Aggregate extends AggregateBase {
130
129
  sessionTraceMode: MODE.OFF
131
130
  });
132
131
  operationalGate.permanentlyDecide(false);
133
- if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest(); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
132
+ if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest({}); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
134
133
  this.#scheduler?.stopTimer(true); // the 'true' arg here will forcibly block any future call to runHarvest, so the last runHarvest above must be prior
135
134
  this.#scheduler = null;
136
135
  };
@@ -149,9 +148,7 @@ export class Aggregate extends AggregateBase {
149
148
  - if trace switches to Full mode, harvest should start (prev: Error) if not already running (prev: Full). */
150
149
  this.ee.on(SESSION_EVENTS.RESUME, () => {
151
150
  const updatedTraceMode = sessionEntity.state.sessionTraceMode;
152
- if (updatedTraceMode === MODE.OFF) stopTracePerm();else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({
153
- needResponse: true
154
- });
151
+ if (updatedTraceMode === MODE.OFF) stopTracePerm();else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({});
155
152
  mostRecentModeKnown = updatedTraceMode;
156
153
  });
157
154
  this.ee.on(SESSION_EVENTS.PAUSE, () => {
@@ -242,15 +239,12 @@ export class Aggregate extends AggregateBase {
242
239
  retryDelay: this.harvestTimeSeconds
243
240
  }, this);
244
241
  this.#scheduler.harvest.on('resources', this.#prepareHarvest.bind(this));
245
- if (dontStartHarvestYet === false) this.#scheduler.runHarvest({
246
- needResponse: true
247
- }); // sends first stn harvest immediately
242
+ if (dontStartHarvestYet === false) this.#scheduler.runHarvest({}); // sends first stn harvest immediately
248
243
  startupBuffer.decide(true); // signal to ALLOW & process data in EE's buffer into internal nodes queued for next harvest
249
244
  }
250
245
  #onHarvestFinished(result) {
251
- if (result.sent && result.responseText && !this.ptid) {
252
- // continue interval harvest only if ptid was returned by server on the first
253
- this.agentRuntime.ptid = this.ptid = result.responseText;
246
+ if (result.sent && !result.failed && !this.#scheduler.started) {
247
+ // continue interval harvest only after first call
254
248
  this.#scheduler.startTimer(this.harvestTimeSeconds);
255
249
  }
256
250
  if (result.sent && result.retry && this.sentTrace) {
@@ -266,15 +260,18 @@ export class Aggregate extends AggregateBase {
266
260
  }
267
261
  #prepareHarvest(options) {
268
262
  if (this.isStandalone) {
269
- if (this.ptid && now() >= MAX_TRACE_DURATION) {
270
- // Perform a final harvest once we hit or exceed the max session trace time
271
- options.isFinalHarvest = true;
272
- this.operationalGate.permanentlyDecide(false);
273
- this.#scheduler.stopTimer(true);
274
- } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
275
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
276
- return;
263
+ if (this.#scheduler.started) {
264
+ if (now() >= MAX_TRACE_DURATION) {
265
+ // Perform a final harvest once we hit or exceed the max session trace time
266
+ options.isFinalHarvest = true;
267
+ this.operationalGate.permanentlyDecide(false);
268
+ this.#scheduler.stopTimer(true);
269
+ } else if (this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
270
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
271
+ return;
272
+ }
277
273
  }
274
+ // else, we must be on the very first harvest (standalone mode), so go to next square
278
275
  } else {
279
276
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
280
277
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -15,6 +15,7 @@ import { gosCDN } from '../../common/window/nreum';
15
15
  import { apiMethods, asyncApiMethods } from './api-methods';
16
16
  import { SR_EVENT_EMITTER_TYPES } from '../../features/session_replay/constants';
17
17
  import { now } from '../../common/timing/now';
18
+ import { MODE } from '../../common/session/constants';
18
19
  export function setTopLevelCallers() {
19
20
  const nr = gosCDN();
20
21
  apiMethods.forEach(f => {
@@ -38,12 +39,17 @@ export function setTopLevelCallers() {
38
39
  return returnVals.length > 1 ? returnVals : returnVals[0];
39
40
  }
40
41
  }
42
+ const replayRunning = {};
41
43
  export function setAPI(agentIdentifier, forceDrain) {
42
44
  let runSoftNavOverSpa = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
43
45
  if (!forceDrain) registerDrain(agentIdentifier, 'api');
44
46
  const apiInterface = {};
45
47
  var instanceEE = ee.get(agentIdentifier);
46
48
  var tracerEE = instanceEE.get('tracer');
49
+ replayRunning[agentIdentifier] = MODE.OFF;
50
+ instanceEE.on(SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, isRunning => {
51
+ replayRunning[agentIdentifier] = isRunning;
52
+ });
47
53
  var prefix = 'api-';
48
54
  var spaPrefix = prefix + 'ixn-';
49
55
 
@@ -186,7 +192,7 @@ export function setAPI(agentIdentifier, forceDrain) {
186
192
  apiInterface.noticeError = function (err, customAttributes) {
187
193
  if (typeof err === 'string') err = new Error(err);
188
194
  handle(SUPPORTABILITY_METRIC_CHANNEL, ['API/noticeError/called'], undefined, FEATURE_NAMES.metrics, instanceEE);
189
- handle('err', [err, now(), false, customAttributes], undefined, FEATURE_NAMES.jserrors, instanceEE);
195
+ handle('err', [err, now(), false, customAttributes, !!replayRunning[agentIdentifier]], undefined, FEATURE_NAMES.jserrors, instanceEE);
190
196
  };
191
197
 
192
198
  // theres no window.load event on non-browser scopes, lazy load immediately
@@ -54,6 +54,7 @@ export function configure(agent) {
54
54
  agent.runSoftNavOverSpa &&= updatedInit.soft_navigations.enabled === true && updatedInit.feature_flags.includes('soft_nav');
55
55
  }
56
56
  runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
57
+ runtime.ptid = agent.agentIdentifier;
57
58
  setRuntime(agent.agentIdentifier, runtime);
58
59
  if (agent.api === undefined) agent.api = setAPI(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
59
60
  if (agent.exposed === undefined) agent.exposed = exposed;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/common/constants/runtime.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,qCAEqB;AAErB;;GAEG;AACH,oCAeK;AAEL,oDAUI;AAEJ,oDAA6F;AAE7F,sCAA2F;AAE3F,qCAAyD;AAEzD,4BAA8E;AAE9E;;;;;;GAMG;AACH,iCAAwE;AAExE,+BAOI;AAEJ,2BAA2E;AAE3E,yCAAqE;AAErE,4BAAyI"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/common/constants/runtime.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,qCAEqB;AAErB;;GAEG;AACH,oCAeK;AAEL,oDAUI;AAEJ,oDAA6F;AAE7F,sCAA2F;AAE3F,qCAAyD;AAEzD,4BAA8E;AAE9E;;;;;;GAMG;AACH,iCAAwE;AAExE,+BAOI;AAEJ,2BAA2E;AAE3E,yCAAqE;AAErE,4BAAgE"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AA6BA;IACE;;;;;OAKG;IACH,uBA0BC;IApBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAenC;;;;aAwEC;IAjEC,8BAA0B;IAC1B,+BAA4B;IAc1B,gCAOqC;IAUrC,4CAiBsC;IAexC,iCAAuB;IAIzB,wBAEC;IAED,sBAEC;IAED;;;OAGG;IACH,QAFa,MAAM,CA6BlB;IAED;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAkBlB;IAED,gBAuBC;IAED;;OAEG;IACH,gBAIC;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CAKnB;IAED,yDAUC;IAED,6DAIC;IAED;;;OAGG;IACH,6BAHW,MAAM,GACJ,MAAM,CAIlB;IAED,gDAaC;IAHG,YAAuD;CAI5D;sBApSqB,gBAAgB;iCAGL,4BAA4B"}
1
+ {"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AA6BA;IACE;;;;;OAKG;IACH,uBA0BC;IApBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAenC;;;;aAyEC;IAlEC,8BAA0B;IAC1B,+BAA4B;IAc1B,gCAOqC;IAUrC,4CAkBsC;IAexC,iCAAuB;IAIzB,wBAEC;IAED,sBAEC;IAED;;;OAGG;IACH,QAFa,MAAM,CA6BlB;IAED;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAkBlB;IAED,gBAuBC;IAED;;OAEG;IACH,gBAIC;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CAKnB;IAED,yDAUC;IAED,6DAIC;IAED;;;OAGG;IACH,6BAHW,MAAM,GACJ,MAAM,CAIlB;IAED,gDAaC;IAHG,YAAuD;CAI5D;sBArSqB,gBAAgB;iCAGL,4BAA4B"}
@@ -2,6 +2,8 @@ export class InteractionTimer extends Timer {
2
2
  onPause: any;
3
3
  onRefresh: any;
4
4
  onResume: any;
5
+ /** used to double-check LS state at resume time */
6
+ readStorage: any;
5
7
  remainingMs: number | undefined;
6
8
  abortController: AbortController | undefined;
7
9
  ee: any;
@@ -1 +1 @@
1
- {"version":3,"file":"interaction-timer.d.ts","sourceRoot":"","sources":["../../../../src/common/timer/interaction-timer.js"],"names":[],"mappings":"AAKA;IAGI,aAAuF;IACvF,eAA6F;IAC7F,cAA0F;IAG1F,gCAA4B;IAM1B,6CAA4C;IAO1C,QAAiB;IAEjB,kDAIC;IAoBP,cAQC;IAED,cAIC;IAED,eAGC;IAED,gCAMC;CACF;sBAhFqB,SAAS"}
1
+ {"version":3,"file":"interaction-timer.d.ts","sourceRoot":"","sources":["../../../../src/common/timer/interaction-timer.js"],"names":[],"mappings":"AAKA;IAGI,aAAuF;IACvF,eAA6F;IAC7F,cAA0F;IAE1F,mDAAmD;IACnD,iBAAmC;IAGnC,gCAA4B;IAM1B,6CAA4C;IAO1C,QAAiB;IAEjB,kDAIC;IAoBP,cAQC;IAED,cAIC;IAED,eAeC;IAED,gCAMC;CACF;sBA/FqB,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH;IA+BE,oBAEC;IAED,yBAEC;IAED,kCAEC;IAED;;;;;OAKG;IACH,8BAJsB,cAAc,aACf,MAAM,WACR,MAAM,QAoBxB;IAED;;;;;OAKG;IACH,uCAHwB,MAAM,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oCAHqB,MAAM,GACf,MAAM,CAIjB;;CACF"}
1
+ {"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;IA+BE,oBAEC;IAED,yBAEC;IAED,kCAEC;IAED;;;;;OAKG;IACH,8BAJsB,cAAc,aACf,MAAM,WACR,MAAM,QAoBxB;IAED;;;;;OAKG;IACH,uCAHwB,MAAM,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oCAHqB,MAAM,GACf,MAAM,CAIjB;;CACF"}
@@ -10,6 +10,7 @@ export class Aggregate extends AggregateBase {
10
10
  bufferedErrorsUnderSpa: {};
11
11
  currentBody: {} | null | undefined;
12
12
  errorOnPage: boolean;
13
+ replayAborted: boolean;
13
14
  onHarvestStarted(options: any): {
14
15
  body: {} | null;
15
16
  qs: {};
@@ -25,7 +26,7 @@ export class Aggregate extends AggregateBase {
25
26
  * @returns {string} A canonical stack string built from the URLs and function names in the given `stackInfo` object.
26
27
  */
27
28
  buildCanonicalStackString(stackInfo: StackInfo): string;
28
- storeError(err: any, time: any, internal: any, customAttributes: any): void;
29
+ storeError(err: any, time: any, internal: any, customAttributes: any, hasReplay: any): void;
29
30
  onInteractionDone(interaction: any, wasSaved: any): void;
30
31
  onSoftNavNotification(interactionId: any, wasFinished: any, softNavAttrs: any): void;
31
32
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAyBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,mDAgCC;IA7BC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,mCAA4B;IAC5B,qBAAwB;IA0B1B;;;MAoBC;IAED,qCAWC;IAED,8BAEC;IAED,oEAMC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED,4EAuFC;IA4BD,yDA6BC;IAED,qFAOC;;CACF;wBAvQY,OAAO,0BAA0B,EAAE,SAAS;8BAN3B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAyBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,mDAmCC;IAhCC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,mCAA4B;IAC5B,qBAAwB;IACxB,uBAA0B;IA4B5B;;;MA2BC;IAED,qCAWC;IAED,8BAEC;IAED,oEAMC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED,4FAsFC;IA4BD,yDA6BC;IAED,qFAOC;;CACF;wBAhRY,OAAO,0BAA0B,EAAE,SAAS;8BAN3B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/instrument/index.js"],"names":[],"mappings":"AAeA;IACE,2BAAiC;IAIjC,mEA4CC;IAvCG,2CAA0C;IAqC5C,yBAA+B;;CAoFlC;+BA5I8B,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/instrument/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IAKjC,mEA+CC;IA1CG,2CAA0C;IAwC5C,yBAA+B;;CAoFlC;+BAjJ8B,6BAA6B"}
@@ -1,6 +1,7 @@
1
1
  export class Aggregate extends AggregateBase {
2
2
  static featureName: string;
3
3
  constructor(agentIdentifier: any, aggregator: any, args: any);
4
+ mode: number;
4
5
  /** The interval to harvest at. This gets overridden if the size of the payload exceeds certain thresholds */
5
6
  harvestTimeSeconds: any;
6
7
  /** Set once the recorder has fully initialized after flag checks and sampling */
@@ -9,14 +10,15 @@ export class Aggregate extends AggregateBase {
9
10
  gzipper: typeof import("fflate").gzipSync | undefined;
10
11
  /** populated with the u8 string lib async */
11
12
  u8: typeof import("fflate").strToU8 | undefined;
12
- mode: any;
13
13
  /** set by BCS response */
14
14
  entitled: boolean;
15
15
  /** set at BCS response, stored in runtime */
16
16
  timeKeeper: any;
17
17
  recorder: any;
18
+ preloaded: boolean;
19
+ errorNoticed: any;
18
20
  scheduler: HarvestScheduler;
19
- errorNoticed: boolean;
21
+ handleError(e: any): void;
20
22
  switchToFull(): void;
21
23
  /**
22
24
  * Evaluate entitlements and sampling before starting feature mechanics, importing and configuring recording library, and setting storage state
@@ -41,6 +43,7 @@ export class Aggregate extends AggregateBase {
41
43
  };
42
44
  body: any;
43
45
  }[] | undefined;
46
+ getCorrectedTimestamp(node: any): any;
44
47
  getHarvestContents(recorderEvents: any): {
45
48
  qs: {
46
49
  browser_monitoring_key: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AA+BA;IACE,2BAAiC;IAEjC,8DAoHC;IAlHC,8GAA8G;IAC9G,wBAAgH;IAChH,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IAGnB,UAAuD;IAEvD,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,cAA8B;IA8B9B,4BAKQ;IAmBN,sBAAwB;IA2C5B,qBAWC;IAED;;;;;;;OAOG;IACH,iCALW,OAAO,cACP,OAAO,iBACP,OAAO,GACL,IAAI,CA6DhB;IAED,2BASC;IAED;;;;;;;;;;;;oBAoCC;IAED;;;;;;;;;;MAmEC;IAED,qCAOC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,yBAUC;IAED,yCAGC;CACF;8BAtX6B,4BAA4B;iCAHzB,2CAA2C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AAgCA;IACE,2BAAiC;IAIjC,8DAsGC;IAzGD,aAAe;IAKb,8GAA8G;IAC9G,wBAAgH;IAChH,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IAEnB,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,cAA8B;IAC9B,mBAAgC;IAChC,kBAA+C;IA4B/C,4BAKQ;IAmDV,0BAMC;IAED,qBAWC;IAED;;;;;;;OAOG;IACH,iCALW,OAAO,cACP,OAAO,iBACP,OAAO,GACL,IAAI,CA8DhB;IAED,2BASC;IAED;;;;;;;;;;;;oBAiDC;IAED,sCAIC;IAED;;;;;;;;;;MAoEC;IAED,qCAOC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,yBAUC;IAED,yCAGC;CACF;8BAxY6B,4BAA4B;iCAHzB,2CAA2C"}
@@ -2,6 +2,7 @@ export const FEATURE_NAME: string;
2
2
  export namespace SR_EVENT_EMITTER_TYPES {
3
3
  let RECORD: string;
4
4
  let PAUSE: string;
5
+ let REPLAY_RUNNING: string;
5
6
  }
6
7
  export const AVG_COMPRESSION: 0.12;
7
8
  export namespace RRWEB_EVENT_TYPES {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/session_replay/constants.js"],"names":[],"mappings":"AAGA,kCAAuD;;;;;AAOvD,mCAAmC;;;;;;;;;AASnC,uCAAuC;AACvC,uCAAuC;AACvC,iCAAiC;AACjC,uCAAuC;AACvC,2GAA2G;AAC3G;;EAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BtF,0CAA0C;AAC1C,uCAAuC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/session_replay/constants.js"],"names":[],"mappings":"AAGA,kCAAuD;;;;;;AAQvD,mCAAmC;;;;;;;;;AASnC,uCAAuC;AACvC,uCAAuC;AACvC,iCAAiC;AACjC,uCAAuC;AACvC,2GAA2G;AAC3G;;EAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BtF,0CAA0C;AAC1C,uCAAuC"}
@@ -1,6 +1,7 @@
1
1
  export class Instrument extends InstrumentBase {
2
2
  static featureName: string;
3
3
  constructor(agentIdentifier: any, aggregator: any, auto?: boolean);
4
+ errorNoticed: boolean;
4
5
  recorder: import("../shared/recorder").Recorder | undefined;
5
6
  #private;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/instrument/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,mEAYC;IAiBC,4DAA6E;;CAKhF;+BAxC8B,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/instrument/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,mEAiBC;IAPK,sBAAwB;IAwB5B,4DAA0F;;CAK7F;+BA7C8B,6BAA6B"}
@@ -1,18 +1,10 @@
1
1
  export class RecorderEvents {
2
- constructor({ canCorrectTimestamps }: {
3
- canCorrectTimestamps: any;
4
- });
5
2
  /** The buffer to hold recorder event nodes */
6
3
  events: any[];
7
4
  /** Payload metadata -- Should indicate when a replay blob started recording. Resets each time a harvest occurs.
8
5
  * cycle timestamps are used as fallbacks if event timestamps cannot be used
9
6
  */
10
7
  cycleTimestamp: number;
11
- /** Payload metadata -- Whether timestamps can be corrected, defaults as false, can be set to true if timekeeper is present at init time. Used to determine
12
- * if harvest needs to re-loop through nodes and correct them before sending. Ideal behavior is to correct them as they flow into the recorder
13
- * to prevent re-looping, but is not always possible since the timekeeper is not set until after page load and the recorder can be preloaded.
14
- */
15
- canCorrectTimestamps: boolean;
16
8
  /** A value which increments with every new mutation node reported. Resets after a harvest is sent */
17
9
  payloadBytesEstimation: number;
18
10
  /** Payload metadata -- Should indicate that the payload being sent has a full DOM snapshot. This can happen
@@ -1 +1 @@
1
- {"version":3,"file":"recorder-events.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder-events.js"],"names":[],"mappings":"AAAA;IACE;;OAyBC;IAxBC,8CAA8C;IAC9C,cAAgB;IAChB;;OAEG;IACH,uBAAgC;IAChC;;;MAGE;IACF,8BAAkD;IAClD,qGAAqG;IACrG,+BAA+B;IAC/B;;;MAGE;IACF,qBAAwB;IACxB,4IAA4I;IAC5I,iBAAoB;IACpB,+HAA+H;IAC/H,kBAAqB;IACrB,0FAA0F;IAC1F,+BAAiC;IAGnC,sBAEC;CACF"}
1
+ {"version":3,"file":"recorder-events.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder-events.js"],"names":[],"mappings":"AAAA;IAEI,8CAA8C;IAC9C,cAAgB;IAChB;;OAEG;IACH,uBAAgC;IAChC,qGAAqG;IACrG,+BAA+B;IAC/B;;;MAGE;IACF,qBAAwB;IACxB,4IAA4I;IAC5I,iBAAoB;IACpB,+HAA+H;IAC/H,kBAAqB;IACrB,0FAA0F;IAC1F,+BAAiC;IAGnC,sBAEC;CACF"}
@@ -15,31 +15,15 @@ export class Recorder {
15
15
  /** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
16
16
  stopRecording: () => void;
17
17
  getEvents(): {
18
- events: CorrectedSessionReplayEvent[];
19
18
  type: string;
19
+ events: any[];
20
20
  cycleTimestamp: number;
21
- canCorrectTimestamps: boolean;
22
21
  payloadBytesEstimation: number;
23
22
  hasSnapshot: boolean;
24
23
  hasMeta: boolean;
25
24
  hasError: boolean;
26
25
  inlinedAllStylesheets: boolean;
27
- } | {
28
- events: any[];
29
- type: string;
30
- cycleTimestamp: number;
31
- payloadBytesEstimation: number;
32
- hasError: boolean;
33
- hasMeta: boolean;
34
- hasSnapshot: boolean;
35
- inlinedAllStylesheets: boolean;
36
26
  };
37
- /**
38
- * Returns time-corrected events. If the events were correctable from the beginning, this correction will have already been applied.
39
- * @param {SessionReplayEvent[]} events The array of buffered SR nodes
40
- * @returns {CorrectedSessionReplayEvent[]}
41
- */
42
- returnCorrectTimestamps(events: SessionReplayEvent[]): CorrectedSessionReplayEvent[];
43
27
  /** Clears the buffer (this.#events), and resets all payload metadata properties */
44
28
  clearBuffer(): void;
45
29
  /** Begin recording using configured recording lib */
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAWA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAA6C;IAC7C,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;;;;;;;;;;;MAiBC;IAED;;;;OAIG;IACH,gCAHW,oBAAoB,GAClB,6BAA6B,CAOzC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAwBC;IAED;;;;;OAKG;IACH,yCA0BC;IAED,0HAA0H;IAC1H,yCA+CC;IAED,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BAvN8B,mBAAmB"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAYA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAA6C;IAC7C,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAiCC;IAED;;;;;OAKG;IACH,yCA0BC;IAED,0HAA0H;IAC1H,yCAgDC;IAED,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BAjN8B,mBAAmB"}
@@ -1,4 +1,12 @@
1
1
  export function isPreloadAllowed(agentId: any): any;
2
2
  export function canImportReplayAgg(agentId: any, sessionMgr: any): boolean;
3
+ export function buildNRMetaNode(timestamp: any, timeKeeper: any): {
4
+ originalTimestamp: any;
5
+ correctedTimestamp: any;
6
+ timestampDiff: number;
7
+ timeKeeperOriginTime: any;
8
+ timeKeeperCorrectedOriginTime: any;
9
+ timeKeeperDiff: number;
10
+ };
3
11
  export function enableSessionTracking(agentId: any): boolean;
4
12
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/utils.js"],"names":[],"mappings":"AAWA,oDAEC;AAED,2EAGC;AAfM,6DAA+H"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/utils.js"],"names":[],"mappings":"AAWA,oDAEC;AAED,2EAGC;AAED;;;;;;;EAUC;AA3BM,6DAA+H"}
@@ -3,10 +3,11 @@ export class Aggregate extends AggregateBase {
3
3
  constructor(agentIdentifier: any, aggregator: any, argsObj: any);
4
4
  agentRuntime: any;
5
5
  resourceObserver: any;
6
- ptid: string | undefined;
6
+ ptid: any;
7
7
  trace: {} | undefined;
8
8
  nodeCount: number | undefined;
9
9
  sentTrace: {} | null | undefined;
10
+ everSent: boolean | undefined;
10
11
  harvestTimeSeconds: any;
11
12
  maxNodesPerHarvest: any;
12
13
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAiCA;IACE,2BAAiC;IAGjC,iEA4IC;IA1IC,kBAA+C;IAK/C,sBAAiD;IACjD,yBAAc;IACd,sBAAe;IACf,8BAAkB;IAClB,iCAAqB;IACrB,wBAA0G;IAC1G,wBAA4G;IAC5G;;4EAEwE;IACxE,kCAAyB;IAGzB,0CAAsC;IA0HxC,sEAcC;IA6CD,oDAOC;IAGD,oCAwBC;IAGD,uEAkBC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDASC;IAID,qCAkBC;IAGD,qEAUC;IAGD,mEAUC;IAGD,yBAeC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAGD;;;;;;;YAkCM;0GAC8F;;YAE9F;0FAC8E;;YAE9E,4IAA4I;;;;;;MAMjJ;IAED,mEA6BC;;CACF;8BA9gB6B,4BAA4B;6BAF7B,2BAA2B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAiCA;IACE,2BAAiC;IAGjC,iEA6IC;IA3IC,kBAA+C;IAK/C,sBAAiD;IACjD,UAAkC;IAClC,sBAAe;IACf,8BAAkB;IAClB,iCAAqB;IACrB,8BAAqB;IACrB,wBAA0G;IAC1G,wBAA4G;IAC5G;;4EAEwE;IACxE,kCAAyB;IAGzB,0CAAsC;IA0HxC,sEAcC;IA8CD,oDAOC;IAGD,oCAwBC;IAGD,uEAkBC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDASC;IAID,qCAkBC;IAGD,qEAUC;IAGD,mEAUC;IAGD,yBAeC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAGD;;;;;;;YAkCM;0GAC8F;;YAE9F;0FAC8E;;YAE9E,4IAA4I;;;;;;MAMjJ;IAED,mEA6BC;;CACF;8BAhhB6B,4BAA4B;6BAF7B,2BAA2B"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAkBA,2CAeC;AAED;;;;IAiDE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EA0GvB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAmBA,2CAeC;AAID;;;;IAuDE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EA0GvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/configure.js"],"names":[],"mappings":"AASA;;GAEG;AACH,oGA+CC"}
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/configure.js"],"names":[],"mappings":"AASA;;GAEG;AACH,oGAgDC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.255.0",
3
+ "version": "1.256.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -168,7 +168,7 @@
168
168
  "dependencies": {
169
169
  "core-js": "^3.26.0",
170
170
  "fflate": "^0.7.4",
171
- "rrweb": "2.0.0-alpha.11",
171
+ "rrweb": "2.0.0-alpha.12",
172
172
  "web-vitals": "^3.1.0"
173
173
  },
174
174
  "devDependencies": {
@@ -74,4 +74,4 @@ export const isIE = Boolean(isBrowserScope && window.document.documentMode) // d
74
74
 
75
75
  export const supportsSendBeacon = !!globalScope.navigator?.sendBeacon
76
76
 
77
- export const offset = Math.floor(globalScope?.performance?.timeOrigin || globalScope?.performance?.timing?.navigationStart || Date.now())
77
+ export const offset = Math.floor(Date.now() - performance.now())
@@ -145,7 +145,7 @@ export class Harvest extends SharedContext {
145
145
  result.addEventListener('loadend', function () {
146
146
  // `this` refers to the XHR object in this scope, do not change this to a fat arrow
147
147
  // status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
148
- const cbResult = { sent: this.status !== 0, status: this.status, xhr: this, fullUrl }
148
+ const cbResult = { sent: this.status !== 0, status: this.status, failed: this.status === 0 || this.status >= 400, xhr: this, fullUrl }
149
149
  if (this.status === 429) {
150
150
  cbResult.retry = true
151
151
  cbResult.delay = harvestScope.tooManyRequestsDelay
@@ -117,7 +117,8 @@ export class SessionEntity {
117
117
  this.write(getModeledObject(this.state, model))
118
118
  },
119
119
  ee: this.ee,
120
- refreshEvents: ['click', 'keydown', 'scroll']
120
+ refreshEvents: ['click', 'keydown', 'scroll'],
121
+ readStorage: () => this.storage.get(this.lookupKey)
121
122
  }, this.state.inactiveAt - Date.now())
122
123
  } else {
123
124
  this.state.inactiveAt = Infinity
@@ -10,6 +10,9 @@ export class InteractionTimer extends Timer {
10
10
  this.onRefresh = typeof opts.onRefresh === 'function' ? opts.onRefresh : () => { /* noop */ }
11
11
  this.onResume = typeof opts.onResume === 'function' ? opts.onResume : () => { /* noop */ }
12
12
 
13
+ /** used to double-check LS state at resume time */
14
+ this.readStorage = opts.readStorage
15
+
13
16
  // used by pause/resume
14
17
  this.remainingMs = undefined
15
18
 
@@ -67,8 +70,20 @@ export class InteractionTimer extends Timer {
67
70
  }
68
71
 
69
72
  resume () {
70
- this.refresh()
71
- this.onResume() // emit resume event after state updated
73
+ try {
74
+ const lsData = this.readStorage()
75
+ const obj = typeof lsData === 'string' ? JSON.parse(lsData) : lsData
76
+ if (isExpired(obj.expiresAt) || isExpired(obj.inactiveAt)) this.end()
77
+ else {
78
+ this.refresh()
79
+ this.onResume() // emit resume event after state updated
80
+ }
81
+ } catch (err) {
82
+ this.end()
83
+ }
84
+ function isExpired (timestamp) {
85
+ return Date.now() > timestamp
86
+ }
72
87
  }
73
88
 
74
89
  refresh (cb, ms) {