@newrelic/browser-agent 1.316.0 → 1.317.0-rc.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 +15 -0
- package/dist/cjs/common/config/configurable.js +1 -1
- package/dist/cjs/common/config/init-types.js +1 -0
- package/dist/cjs/common/config/init.js +6 -4
- package/dist/cjs/common/constants/env.cdn.js +2 -2
- package/dist/cjs/common/constants/env.npm.js +2 -2
- package/dist/cjs/common/constants/events.js +26 -0
- package/dist/cjs/common/harvest/harvester.js +9 -217
- package/dist/cjs/common/harvest/send.js +232 -0
- package/dist/cjs/common/harvest/types.js +9 -5
- package/dist/cjs/common/payloads/payloads.js +127 -0
- package/dist/cjs/common/serialize/bel-serializer.js +4 -3
- package/dist/cjs/common/session/session-entity.js +8 -8
- package/dist/cjs/common/util/data-size.js +2 -2
- package/dist/cjs/common/util/obfuscate.js +147 -3
- package/dist/cjs/common/v2/mfe-vitals.js +286 -0
- package/dist/cjs/common/wrap/wrap-websocket.js +2 -1
- package/dist/cjs/common/wrap/wrap-xhr.js +1 -1
- package/dist/cjs/features/ajax/aggregate/gql.js +40 -1
- package/dist/cjs/features/ajax/aggregate/index.js +51 -13
- package/dist/cjs/features/ajax/constants.js +6 -1
- package/dist/cjs/features/ajax/instrument/index.js +105 -17
- package/dist/cjs/features/generic_events/aggregate/index.js +15 -10
- package/dist/cjs/features/generic_events/constants.js +3 -2
- package/dist/cjs/features/jserrors/aggregate/format-stack-trace.js +2 -2
- package/dist/cjs/features/jserrors/aggregate/index.js +12 -3
- package/dist/cjs/features/logging/aggregate/index.js +12 -8
- package/dist/cjs/features/metrics/aggregate/index.js +5 -1
- package/dist/cjs/features/page_view_event/aggregate/index.js +72 -33
- package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -1
- package/dist/cjs/features/session_replay/aggregate/index.js +39 -29
- package/dist/cjs/features/session_trace/aggregate/index.js +35 -29
- package/dist/cjs/features/session_trace/constants.js +17 -3
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +36 -5
- package/dist/cjs/features/soft_navigations/aggregate/index.js +7 -1
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +6 -4
- package/dist/cjs/features/utils/aggregate-base.js +4 -3
- package/dist/cjs/loaders/api/register.js +26 -4
- package/dist/esm/common/config/configurable.js +1 -1
- package/dist/esm/common/config/init-types.js +1 -0
- package/dist/esm/common/config/init.js +3 -1
- package/dist/esm/common/constants/env.cdn.js +2 -2
- package/dist/esm/common/constants/env.npm.js +2 -2
- package/dist/esm/common/constants/events.js +20 -0
- package/dist/esm/common/harvest/harvester.js +9 -217
- package/dist/esm/common/harvest/send.js +226 -0
- package/dist/esm/common/harvest/types.js +9 -5
- package/dist/esm/common/payloads/payloads.js +118 -0
- package/dist/esm/common/serialize/bel-serializer.js +4 -3
- package/dist/esm/common/session/session-entity.js +9 -9
- package/dist/esm/common/util/data-size.js +2 -2
- package/dist/esm/common/util/obfuscate.js +147 -3
- package/dist/esm/common/v2/mfe-vitals.js +281 -0
- package/dist/esm/common/wrap/wrap-websocket.js +2 -1
- package/dist/esm/common/wrap/wrap-xhr.js +1 -1
- package/dist/esm/features/ajax/aggregate/gql.js +39 -1
- package/dist/esm/features/ajax/aggregate/index.js +52 -14
- package/dist/esm/features/ajax/constants.js +5 -0
- package/dist/esm/features/ajax/instrument/index.js +106 -18
- package/dist/esm/features/generic_events/aggregate/index.js +15 -10
- package/dist/esm/features/generic_events/constants.js +3 -2
- package/dist/esm/features/jserrors/aggregate/format-stack-trace.js +2 -2
- package/dist/esm/features/jserrors/aggregate/index.js +12 -3
- package/dist/esm/features/logging/aggregate/index.js +12 -8
- package/dist/esm/features/metrics/aggregate/index.js +5 -1
- package/dist/esm/features/page_view_event/aggregate/index.js +71 -32
- package/dist/esm/features/page_view_timing/aggregate/index.js +6 -1
- package/dist/esm/features/session_replay/aggregate/index.js +39 -29
- package/dist/esm/features/session_trace/aggregate/index.js +36 -30
- package/dist/esm/features/session_trace/constants.js +16 -2
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +36 -5
- package/dist/esm/features/soft_navigations/aggregate/index.js +7 -1
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +6 -4
- package/dist/esm/features/utils/aggregate-base.js +4 -3
- package/dist/esm/loaders/api/register.js +26 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +4 -0
- package/dist/types/common/config/init-types.d.ts.map +1 -1
- package/dist/types/common/config/init.d.ts.map +1 -1
- package/dist/types/common/constants/events.d.ts +16 -0
- package/dist/types/common/constants/events.d.ts.map +1 -0
- package/dist/types/common/harvest/harvester.d.ts +2 -16
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/harvest/send.d.ts +9 -0
- package/dist/types/common/harvest/send.d.ts.map +1 -0
- package/dist/types/common/harvest/types.d.ts +39 -10
- package/dist/types/common/harvest/types.d.ts.map +1 -1
- package/dist/types/common/payloads/payloads.d.ts +42 -0
- package/dist/types/common/payloads/payloads.d.ts.map +1 -0
- package/dist/types/common/serialize/bel-serializer.d.ts +1 -1
- package/dist/types/common/serialize/bel-serializer.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/util/obfuscate.d.ts +23 -2
- package/dist/types/common/util/obfuscate.d.ts.map +1 -1
- package/dist/types/common/v2/mfe-vitals.d.ts +14 -0
- package/dist/types/common/v2/mfe-vitals.d.ts.map +1 -0
- package/dist/types/common/wrap/wrap-websocket.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/gql.d.ts +8 -0
- package/dist/types/features/ajax/aggregate/gql.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +2 -0
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/ajax/constants.d.ts +5 -0
- package/dist/types/features/ajax/constants.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +3 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/constants.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +8 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +3 -1
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts +2 -0
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +3 -0
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -0
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +4 -2
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +3 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/constants.d.ts +17 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +6 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +3 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +3 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +0 -1
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/loaders/api/register.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/common/config/configurable.js +1 -1
- package/src/common/config/init-types.js +1 -0
- package/src/common/config/init.js +2 -1
- package/src/common/constants/events.js +20 -0
- package/src/common/harvest/harvester.js +9 -201
- package/src/common/harvest/send.js +209 -0
- package/src/common/harvest/types.js +9 -5
- package/src/common/payloads/payloads.js +135 -0
- package/src/common/serialize/bel-serializer.js +4 -3
- package/src/common/session/session-entity.js +8 -9
- package/src/common/util/data-size.js +2 -2
- package/src/common/util/obfuscate.js +154 -3
- package/src/common/v2/mfe-vitals.js +260 -0
- package/src/common/wrap/wrap-websocket.js +2 -1
- package/src/common/wrap/wrap-xhr.js +1 -1
- package/src/features/ajax/aggregate/gql.js +42 -1
- package/src/features/ajax/aggregate/index.js +43 -13
- package/src/features/ajax/constants.js +5 -1
- package/src/features/ajax/instrument/index.js +114 -18
- package/src/features/generic_events/aggregate/index.js +14 -9
- package/src/features/generic_events/constants.js +3 -2
- package/src/features/jserrors/aggregate/format-stack-trace.js +3 -3
- package/src/features/jserrors/aggregate/index.js +12 -3
- package/src/features/logging/aggregate/index.js +12 -11
- package/src/features/metrics/aggregate/index.js +5 -1
- package/src/features/page_view_event/aggregate/index.js +58 -29
- package/src/features/page_view_timing/aggregate/index.js +6 -1
- package/src/features/session_replay/aggregate/index.js +37 -28
- package/src/features/session_trace/aggregate/index.js +37 -30
- package/src/features/session_trace/constants.js +7 -1
- package/src/features/soft_navigations/aggregate/ajax-node.js +26 -5
- package/src/features/soft_navigations/aggregate/index.js +7 -1
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/src/features/soft_navigations/aggregate/interaction.js +6 -4
- package/src/features/utils/aggregate-base.js +3 -3
- package/src/loaders/api/register.js +24 -4
|
@@ -10,10 +10,11 @@ import { AggregateBase } from '../../utils/aggregate-base'
|
|
|
10
10
|
import { warn } from '../../../common/util/console'
|
|
11
11
|
import { now } from '../../../common/timing/now'
|
|
12
12
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
13
|
-
import {
|
|
13
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
14
14
|
import { UserActionsAggregator } from './user-actions/user-actions-aggregator'
|
|
15
15
|
import { isIFrameWindow } from '../../../common/dom/iframe'
|
|
16
16
|
import { isPureObject } from '../../../common/util/type-check'
|
|
17
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
17
18
|
import { getVersion2Attributes, getVersion2DuplicationAttributes, shouldDuplicate } from '../../../common/v2/utils'
|
|
18
19
|
|
|
19
20
|
export class Aggregate extends AggregateBase {
|
|
@@ -24,6 +25,10 @@ export class Aggregate extends AggregateBase {
|
|
|
24
25
|
super(agentRef, FEATURE_NAME)
|
|
25
26
|
this.referrerUrl = (isBrowserScope && document.referrer) ? cleanURL(document.referrer) : undefined
|
|
26
27
|
|
|
28
|
+
// Create generic obfuscator (no specific event types) since this feature handles multiple event types
|
|
29
|
+
// Will check each event's eventType property at runtime against obfuscation rules
|
|
30
|
+
this.obfuscator = new Obfuscator(agentRef)
|
|
31
|
+
|
|
27
32
|
this.waitForFlags(['ins']).then(([ins]) => {
|
|
28
33
|
if (!ins) {
|
|
29
34
|
this.blocked = true
|
|
@@ -46,7 +51,7 @@ export class Aggregate extends AggregateBase {
|
|
|
46
51
|
registerHandler('api-addPageAction', (timestamp, name, attributes, target) => {
|
|
47
52
|
this.addEvent({
|
|
48
53
|
...attributes,
|
|
49
|
-
eventType:
|
|
54
|
+
eventType: EVENT_TYPES.PA,
|
|
50
55
|
timestamp: this.#toEpoch(timestamp),
|
|
51
56
|
timeSinceLoad: timestamp / 1000,
|
|
52
57
|
actionName: name,
|
|
@@ -73,7 +78,7 @@ export class Aggregate extends AggregateBase {
|
|
|
73
78
|
|
|
74
79
|
aggregatedUserAction.targets.forEach(mfeTarget => {
|
|
75
80
|
const userActionEvent = {
|
|
76
|
-
eventType:
|
|
81
|
+
eventType: EVENT_TYPES.UA,
|
|
77
82
|
timestamp: this.#toEpoch(timeStamp),
|
|
78
83
|
action: type,
|
|
79
84
|
actionCount: aggregatedUserAction.count,
|
|
@@ -152,7 +157,7 @@ export class Aggregate extends AggregateBase {
|
|
|
152
157
|
const detailObj = agentRef.init.performance.capture_detail ? createDetailAttrs(entry.detail) : {}
|
|
153
158
|
this.addEvent({
|
|
154
159
|
...detailObj,
|
|
155
|
-
eventType:
|
|
160
|
+
eventType: EVENT_TYPES.BP,
|
|
156
161
|
timestamp: this.#toEpoch(entry.startTime),
|
|
157
162
|
entryName: entry.name,
|
|
158
163
|
entryDuration: entry.duration,
|
|
@@ -217,7 +222,7 @@ export class Aggregate extends AggregateBase {
|
|
|
217
222
|
this.reportSupportabilityMetric('Generic/Performance/Resource/Seen')
|
|
218
223
|
const event = {
|
|
219
224
|
...entryObject,
|
|
220
|
-
eventType:
|
|
225
|
+
eventType: EVENT_TYPES.BP,
|
|
221
226
|
timestamp: this.#toEpoch(entryObject.startTime),
|
|
222
227
|
entryName: cleanURL(name),
|
|
223
228
|
entryDuration: duration,
|
|
@@ -236,7 +241,7 @@ export class Aggregate extends AggregateBase {
|
|
|
236
241
|
|
|
237
242
|
const event = {
|
|
238
243
|
...customAttributes,
|
|
239
|
-
eventType:
|
|
244
|
+
eventType: EVENT_TYPES.BP,
|
|
240
245
|
timestamp: this.#toEpoch(start),
|
|
241
246
|
entryName: n,
|
|
242
247
|
entryDuration: duration,
|
|
@@ -250,7 +255,7 @@ export class Aggregate extends AggregateBase {
|
|
|
250
255
|
registerHandler('ws-complete', (nrData) => {
|
|
251
256
|
const event = {
|
|
252
257
|
...nrData,
|
|
253
|
-
eventType:
|
|
258
|
+
eventType: EVENT_TYPES.WS,
|
|
254
259
|
timestamp: this.#toEpoch(nrData.timestamp),
|
|
255
260
|
openedAt: this.#toEpoch(nrData.openedAt),
|
|
256
261
|
closedAt: this.#toEpoch(nrData.closedAt)
|
|
@@ -266,7 +271,7 @@ export class Aggregate extends AggregateBase {
|
|
|
266
271
|
if (!agentRef.init.feature_flags.includes('no_spv')) {
|
|
267
272
|
registerHandler('spv', (evt) => {
|
|
268
273
|
this.addEvent({
|
|
269
|
-
eventType:
|
|
274
|
+
eventType: EVENT_TYPES.SPV,
|
|
270
275
|
timestamp: this.#toEpoch(evt.timeStamp),
|
|
271
276
|
blockedUri: evt.blockedURI,
|
|
272
277
|
documentUri: evt.documentURI,
|
|
@@ -335,7 +340,7 @@ export class Aggregate extends AggregateBase {
|
|
|
335
340
|
}
|
|
336
341
|
|
|
337
342
|
serializer (eventBuffer) {
|
|
338
|
-
return
|
|
343
|
+
return this.obfuscator.traverseAndObfuscateEvents({ ins: eventBuffer })
|
|
339
344
|
}
|
|
340
345
|
|
|
341
346
|
queryStringsBuilder () {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
+
import { EVENT_TYPES } from '../../common/constants/events'
|
|
5
6
|
import { FEATURE_NAMES } from '../../loaders/features/features'
|
|
6
7
|
|
|
7
8
|
export const FEATURE_NAME = FEATURE_NAMES.genericEvents
|
|
@@ -14,7 +15,7 @@ export const RAGE_CLICK_THRESHOLD_MS = 1000
|
|
|
14
15
|
|
|
15
16
|
export const FRUSTRATION_TIMEOUT_MS = 2000
|
|
16
17
|
|
|
17
|
-
export const RESERVED_EVENT_TYPES = [
|
|
18
|
+
export const RESERVED_EVENT_TYPES = [EVENT_TYPES.PA, EVENT_TYPES.UA, EVENT_TYPES.BP]
|
|
18
19
|
|
|
19
20
|
export const FEATURE_FLAGS = {
|
|
20
21
|
RESOURCES: 'experimental.resources',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -10,7 +10,7 @@ export function formatStackTrace (stackLines) {
|
|
|
10
10
|
return truncateStackLines(stackLines).replace(stripNewlinesRegex, '')
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// takes array of stack lines and returns string with top 50 and
|
|
13
|
+
// takes array of stack lines and returns string with top 50 and bottom 50 lines
|
|
14
14
|
function truncateStackLines (stackLines) {
|
|
15
15
|
var stackString
|
|
16
16
|
if (stackLines.length > 100) {
|
|
@@ -26,5 +26,5 @@ function truncateStackLines (stackLines) {
|
|
|
26
26
|
|
|
27
27
|
// truncates stack string to limit what is sent to backend
|
|
28
28
|
export function truncateSize (stackString) {
|
|
29
|
-
return
|
|
29
|
+
return stackString.length > MAX_STACK_TRACE_LENGTH ? stackString.substr(0, MAX_STACK_TRACE_LENGTH) : stackString
|
|
30
30
|
}
|
|
@@ -17,11 +17,12 @@ import { FEATURE_NAME } from '../constants'
|
|
|
17
17
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
18
18
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
19
19
|
import { now } from '../../../common/timing/now'
|
|
20
|
-
import {
|
|
20
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
21
21
|
import { evaluateInternalError } from './internal-errors'
|
|
22
22
|
import { getRegisteredTargetsFromFilename, getVersion2Attributes, getVersion2DuplicationAttributes, shouldDuplicate } from '../../../common/v2/utils'
|
|
23
23
|
import { buildCauseString } from './cause-string'
|
|
24
24
|
import { ShortCircuit } from '../../../common/util/short-circuit'
|
|
25
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
|
|
@@ -39,6 +40,10 @@ export class Aggregate extends AggregateBase {
|
|
|
39
40
|
this.pageviewReported = {}
|
|
40
41
|
this.errorOnPage = false
|
|
41
42
|
|
|
43
|
+
// Create obfuscators for each event type this feature handles
|
|
44
|
+
this.errorObfuscator = new Obfuscator(agentRef, EVENT_TYPES.JSE)
|
|
45
|
+
this.xhrObfuscator = new Obfuscator(agentRef, EVENT_TYPES.AJAX)
|
|
46
|
+
|
|
42
47
|
register('err', this.processError.bind(this), this.featureName, this.ee)
|
|
43
48
|
register('ierr', this.processError.bind(this), this.featureName, this.ee)
|
|
44
49
|
register('returnJserror', (jsErrorEvent, softNavAttrs) => this.#storeJserrorForHarvest(jsErrorEvent, softNavAttrs), this.featureName, this.ee)
|
|
@@ -55,7 +60,11 @@ export class Aggregate extends AggregateBase {
|
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
serializer (aggregatorTypeToBucketsMap) {
|
|
58
|
-
return
|
|
63
|
+
return {
|
|
64
|
+
err: this.errorObfuscator.traverseAndObfuscateEvents(aggregatorTypeToBucketsMap.err),
|
|
65
|
+
ierr: this.errorObfuscator.traverseAndObfuscateEvents(aggregatorTypeToBucketsMap.ierr),
|
|
66
|
+
xhr: this.xhrObfuscator.traverseAndObfuscateEvents(aggregatorTypeToBucketsMap.xhr)
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
queryStringsBuilder (aggregatorTakeReturnedData) {
|
|
@@ -258,7 +267,7 @@ export class Aggregate extends AggregateBase {
|
|
|
258
267
|
params.stack_trace = truncateSize(stackInfo.stackString)
|
|
259
268
|
this.observedAt[bucketHash] = Math.floor(this.agentRef.runtime.timeKeeper.correctRelativeTimestamp(time))
|
|
260
269
|
} else {
|
|
261
|
-
params.browser_stack_hash = stringHashCode(stackInfo.stackString)
|
|
270
|
+
params.browser_stack_hash = stringHashCode(truncateSize(stackInfo.stackString))
|
|
262
271
|
}
|
|
263
272
|
params.releaseIds = stringify(this.agentRef.runtime.releaseIds)
|
|
264
273
|
|
|
@@ -9,11 +9,12 @@ import { AggregateBase } from '../../utils/aggregate-base'
|
|
|
9
9
|
import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL, LOG_LEVELS, LOGGING_MODE } from '../constants'
|
|
10
10
|
import { Log } from '../shared/log'
|
|
11
11
|
import { isValidLogLevel } from '../shared/utils'
|
|
12
|
-
import {
|
|
12
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
13
13
|
import { SESSION_EVENT_TYPES, SESSION_EVENTS } from '../../../common/session/constants'
|
|
14
14
|
import { ABORT_REASONS } from '../../session_replay/constants'
|
|
15
15
|
import { canEnableSessionTracking } from '../../utils/feature-gates'
|
|
16
16
|
import { getVersion2Attributes, getVersion2DuplicationAttributes, shouldDuplicate } from '../../../common/v2/utils'
|
|
17
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
17
18
|
|
|
18
19
|
const LOGGING_EVENT = 'Logging/Event/'
|
|
19
20
|
|
|
@@ -31,6 +32,9 @@ export class Aggregate extends AggregateBase {
|
|
|
31
32
|
this.harvestOpts.raw = true
|
|
32
33
|
super.customAttributesAreSeparate = true
|
|
33
34
|
|
|
35
|
+
// Create obfuscator for log entries
|
|
36
|
+
this.obfuscator = new Obfuscator(agentRef, EVENT_TYPES.LOG)
|
|
37
|
+
|
|
34
38
|
// The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
|
|
35
39
|
this.ee.on(SESSION_EVENTS.RESET, () => {
|
|
36
40
|
this.abort(ABORT_REASONS.RESET)
|
|
@@ -48,7 +52,7 @@ export class Aggregate extends AggregateBase {
|
|
|
48
52
|
this.loggingMode ??= { auto, api } // likewise, don't want to overwrite the mode if it was set already
|
|
49
53
|
const session = this.agentRef.runtime.session
|
|
50
54
|
if (canEnableSessionTracking(agentRef.init) && session) {
|
|
51
|
-
if (session.
|
|
55
|
+
if (session.state.loggingMode === null || session.state.logApiMode === null) this.#writeToStorage(this.loggingMode)
|
|
52
56
|
else updateLocalLoggingMode(session.state.loggingMode, session.state.logApiMode)
|
|
53
57
|
}
|
|
54
58
|
if (this.loggingMode.auto === LOGGING_MODE.OFF && this.loggingMode.api === LOGGING_MODE.OFF) {
|
|
@@ -119,7 +123,7 @@ export class Aggregate extends AggregateBase {
|
|
|
119
123
|
common: {
|
|
120
124
|
/** Attributes in the `common` section are added to `all` logs generated in the payload */
|
|
121
125
|
attributes: {
|
|
122
|
-
...(
|
|
126
|
+
...(this.obfuscator.traverseAndObfuscateEvents(this.agentRef.info.jsAttributes)),
|
|
123
127
|
...(this.harvestEndpointVersion === 1 && {
|
|
124
128
|
'entity.guid': this.agentRef.runtime.appMetadata.agents[0].entityGuid,
|
|
125
129
|
appId: this.agentRef.info.applicationID
|
|
@@ -139,10 +143,7 @@ export class Aggregate extends AggregateBase {
|
|
|
139
143
|
}
|
|
140
144
|
},
|
|
141
145
|
/** logs section contains individual unique log entries */
|
|
142
|
-
logs:
|
|
143
|
-
eventBuffer,
|
|
144
|
-
this.obfuscator.obfuscateString.bind(this.obfuscator), 'string'
|
|
145
|
-
)
|
|
146
|
+
logs: this.obfuscator.traverseAndObfuscateEvents(eventBuffer)
|
|
146
147
|
}]
|
|
147
148
|
}
|
|
148
149
|
|
|
@@ -162,14 +163,14 @@ export class Aggregate extends AggregateBase {
|
|
|
162
163
|
auto: LOGGING_MODE.OFF,
|
|
163
164
|
api: LOGGING_MODE.OFF
|
|
164
165
|
}
|
|
165
|
-
this.#
|
|
166
|
+
this.#writeToStorage(this.loggingMode)
|
|
166
167
|
this.deregisterDrain()
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
#
|
|
170
|
+
#writeToStorage (logModes) {
|
|
170
171
|
this.agentRef.runtime.session?.write({
|
|
171
|
-
loggingMode:
|
|
172
|
-
logApiMode:
|
|
172
|
+
loggingMode: logModes.auto,
|
|
173
|
+
logApiMode: logModes.api
|
|
173
174
|
})
|
|
174
175
|
}
|
|
175
176
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
@@ -12,6 +12,7 @@ import { isBrowserScope, isWorkerScope } from '../../../common/constants/runtime
|
|
|
12
12
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
13
13
|
import { isIFrameWindow } from '../../../common/dom/iframe'
|
|
14
14
|
import { evaluateHarvestMetadata } from './harvest-metadata'
|
|
15
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
15
16
|
// import { WEBSOCKET_TAG } from '../../../common/wrap/wrap-websocket'
|
|
16
17
|
// import { handleWebsocketEvents } from './websocket-detection'
|
|
17
18
|
|
|
@@ -21,6 +22,9 @@ export class Aggregate extends AggregateBase {
|
|
|
21
22
|
super(agentRef, FEATURE_NAME)
|
|
22
23
|
this.harvestOpts.aggregatorTypes = ['cm', 'sm'] // the types in EventAggregator this feature cares about
|
|
23
24
|
|
|
25
|
+
// Create a generic obfuscator for checking if rules are configured
|
|
26
|
+
this.obfuscator = new Obfuscator(agentRef)
|
|
27
|
+
|
|
24
28
|
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
25
29
|
this.harvestMetadata = {}
|
|
26
30
|
this.harvestOpts.beforeUnload = () => {
|
|
@@ -15,11 +15,13 @@ import { firstPaint } from '../../../common/vitals/first-paint'
|
|
|
15
15
|
import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte'
|
|
16
16
|
import { now } from '../../../common/timing/now'
|
|
17
17
|
import { TimeKeeper } from '../../../common/timing/time-keeper'
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { send } from '../../../common/harvest/send'
|
|
19
|
+
import { canEnableSessionTracking } from '../../utils/feature-gates'
|
|
20
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
20
21
|
import { FEATURE_NAMES, FEATURE_TO_ENDPOINT } from '../../../loaders/features/features'
|
|
21
22
|
import { getSubmitMethod } from '../../../common/util/submit-data'
|
|
22
23
|
import { webdriverDetected } from '../../../common/util/webdriver-detection'
|
|
24
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
23
25
|
|
|
24
26
|
export class Aggregate extends AggregateBase {
|
|
25
27
|
static featureName = CONSTANTS.FEATURE_NAME
|
|
@@ -27,6 +29,7 @@ export class Aggregate extends AggregateBase {
|
|
|
27
29
|
constructor (agentRef) {
|
|
28
30
|
super(agentRef, CONSTANTS.FEATURE_NAME)
|
|
29
31
|
|
|
32
|
+
this.isSessionTrackingEnabled = canEnableSessionTracking(agentRef.init) && !!agentRef.runtime.session
|
|
30
33
|
this.sentRum = false // flag to facilitate calling sendRum() once externally (by the consent API in agent-session.js)
|
|
31
34
|
|
|
32
35
|
this.timeToFirstByte = 0
|
|
@@ -34,9 +37,23 @@ export class Aggregate extends AggregateBase {
|
|
|
34
37
|
this.firstByteToDomContent = 0 // our "dom processing" duration
|
|
35
38
|
this.retries = 0
|
|
36
39
|
|
|
40
|
+
// Create obfuscator for page view events
|
|
41
|
+
this.obfuscator = new Obfuscator(agentRef, EVENT_TYPES.PVE)
|
|
42
|
+
|
|
37
43
|
agentRef.runtime.timeKeeper = new TimeKeeper(agentRef.runtime.session)
|
|
38
44
|
|
|
39
45
|
if (isBrowserScope) {
|
|
46
|
+
const cached = this.isSessionTrackingEnabled && agentRef.runtime.session?.state.cachedRumResponse
|
|
47
|
+
if (cached) {
|
|
48
|
+
const { app: cachedApp, ...cachedFlags } = cached
|
|
49
|
+
|
|
50
|
+
// set the agent runtime objects that require the rum response or entity guid
|
|
51
|
+
if (!Object.keys(this.agentRef.runtime.appMetadata).length) agentRef.runtime.appMetadata = cachedApp
|
|
52
|
+
this.drain()
|
|
53
|
+
agentRef.runtime.harvester.startTimer()
|
|
54
|
+
activateFeatures(cachedFlags, agentRef)
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
timeToFirstByte.subscribe(({ value, attrs }) => {
|
|
41
58
|
const navEntry = attrs.navigationEntry
|
|
42
59
|
this.timeToFirstByte = Math.max(value, this.timeToFirstByte)
|
|
@@ -81,9 +98,9 @@ export class Aggregate extends AggregateBase {
|
|
|
81
98
|
at: info.atts
|
|
82
99
|
}
|
|
83
100
|
|
|
84
|
-
if (this.agentRef.runtime.session) queryParameters.fsh = Number(this.agentRef.runtime.session.
|
|
101
|
+
if (this.agentRef.runtime.session) queryParameters.fsh = Number(!this.agentRef.runtime.session.state.cachedRumResponse)
|
|
85
102
|
|
|
86
|
-
let body =
|
|
103
|
+
let body = this.obfuscator.traverseAndObfuscateEvents({ ja: { ...customAttributes, webdriverDetected } })
|
|
87
104
|
|
|
88
105
|
if (globalScope.performance) {
|
|
89
106
|
const navTimingEntry = getNavigationEntry()
|
|
@@ -127,6 +144,7 @@ export class Aggregate extends AggregateBase {
|
|
|
127
144
|
postHarvestCleanup ({ sent, status, responseText, xhr, retry }) {
|
|
128
145
|
const rumEndTime = now()
|
|
129
146
|
let app, flags
|
|
147
|
+
const hasCachedRumResponse = !!this.agentRef.runtime.session?.state.cachedRumResponse
|
|
130
148
|
try {
|
|
131
149
|
({ app, ...flags } = JSON.parse(responseText))
|
|
132
150
|
} catch (error) {
|
|
@@ -134,16 +152,24 @@ export class Aggregate extends AggregateBase {
|
|
|
134
152
|
warn(53, error)
|
|
135
153
|
}
|
|
136
154
|
|
|
137
|
-
|
|
155
|
+
const shouldCacheResponse = this.isSessionTrackingEnabled && !hasCachedRumResponse && !!app
|
|
156
|
+
if (hasCachedRumResponse) {
|
|
157
|
+
let { app: cachedApp, ...cachedFlags } = this.agentRef.runtime.session.state.cachedRumResponse
|
|
158
|
+
app ??= cachedApp
|
|
159
|
+
flags = cachedFlags
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
super.postHarvestCleanup({ sent, retry: retry && !hasCachedRumResponse }) // this will set isRetrying & re-buffer the body if request is to be retried
|
|
163
|
+
|
|
138
164
|
if (this.isRetrying && this.retries++ < 1) { // Only retry once
|
|
139
165
|
setTimeout(() => this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
140
166
|
sendEmptyBody: true
|
|
141
167
|
}), 5000) // Retry sending the RUM event after 5 seconds
|
|
142
168
|
return
|
|
143
169
|
}
|
|
170
|
+
|
|
144
171
|
if (status >= 400 || status === 0) {
|
|
145
172
|
warn(18, status)
|
|
146
|
-
this.blocked = true
|
|
147
173
|
|
|
148
174
|
// Get estimated payload size of our backlog
|
|
149
175
|
const textEncoder = new TextEncoder()
|
|
@@ -155,16 +181,24 @@ export class Aggregate extends AggregateBase {
|
|
|
155
181
|
}, 0)
|
|
156
182
|
const BCSError = 'BCS/Error/'
|
|
157
183
|
// Send SMs about failed RUM request
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
name: BCSError + status
|
|
162
|
-
},
|
|
163
|
-
stats: {
|
|
164
|
-
c: 1
|
|
165
|
-
}
|
|
184
|
+
const sm = [{
|
|
185
|
+
params: {
|
|
186
|
+
name: BCSError + status
|
|
166
187
|
},
|
|
167
|
-
{
|
|
188
|
+
stats: {
|
|
189
|
+
c: 1
|
|
190
|
+
}
|
|
191
|
+
}, {
|
|
192
|
+
params: {
|
|
193
|
+
name: BCSError + 'Duration/Ms'
|
|
194
|
+
},
|
|
195
|
+
stats: {
|
|
196
|
+
c: 1,
|
|
197
|
+
t: rumEndTime - this.rumStartTime
|
|
198
|
+
}
|
|
199
|
+
}]
|
|
200
|
+
if (!hasCachedRumResponse) {
|
|
201
|
+
sm.push({
|
|
168
202
|
params: {
|
|
169
203
|
name: BCSError + 'Dropped/Bytes'
|
|
170
204
|
},
|
|
@@ -172,28 +206,23 @@ export class Aggregate extends AggregateBase {
|
|
|
172
206
|
c: 1,
|
|
173
207
|
t: payloadSize
|
|
174
208
|
}
|
|
175
|
-
}
|
|
176
|
-
{
|
|
177
|
-
params: {
|
|
178
|
-
name: BCSError + 'Duration/Ms'
|
|
179
|
-
},
|
|
180
|
-
stats: {
|
|
181
|
-
c: 1,
|
|
182
|
-
t: rumEndTime - this.rumStartTime
|
|
183
|
-
}
|
|
184
|
-
}]
|
|
209
|
+
})
|
|
185
210
|
}
|
|
186
211
|
|
|
187
212
|
send(this.agentRef, {
|
|
188
213
|
endpoint: FEATURE_TO_ENDPOINT[FEATURE_NAMES.metrics],
|
|
189
|
-
payload: { body },
|
|
214
|
+
payload: { body: { sm } },
|
|
190
215
|
submitMethod: getSubmitMethod(),
|
|
191
216
|
featureName: FEATURE_NAMES.metrics
|
|
192
217
|
})
|
|
193
218
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
219
|
+
if (!hasCachedRumResponse) {
|
|
220
|
+
this.blocked = true
|
|
221
|
+
this.ee.abort()
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
} else if (shouldCacheResponse) {
|
|
225
|
+
this.agentRef.runtime.session.write({ cachedRumResponse: { app, ...flags } })
|
|
197
226
|
}
|
|
198
227
|
|
|
199
228
|
try {
|
|
@@ -9,6 +9,7 @@ import { handle } from '../../../common/event-emitter/handle'
|
|
|
9
9
|
import { FEATURE_NAME } from '../constants'
|
|
10
10
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
11
11
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
12
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
12
13
|
import { cumulativeLayoutShift } from '../../../common/vitals/cumulative-layout-shift'
|
|
13
14
|
import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint'
|
|
14
15
|
import { firstPaint } from '../../../common/vitals/first-paint'
|
|
@@ -21,6 +22,7 @@ import { eventOrigin } from '../../../common/util/event-origin'
|
|
|
21
22
|
import { loadTime } from '../../../common/vitals/load-time'
|
|
22
23
|
import { webdriverDetected } from '../../../common/util/webdriver-detection'
|
|
23
24
|
import { cleanURL } from '../../../common/url/clean-url'
|
|
25
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
24
26
|
|
|
25
27
|
export class Aggregate extends AggregateBase {
|
|
26
28
|
static featureName = FEATURE_NAME
|
|
@@ -36,6 +38,9 @@ export class Aggregate extends AggregateBase {
|
|
|
36
38
|
|
|
37
39
|
super.customAttributesAreSeparate = true
|
|
38
40
|
|
|
41
|
+
// Create obfuscator for page view timing events
|
|
42
|
+
this.obfuscator = new Obfuscator(agentRef, EVENT_TYPES.PVT)
|
|
43
|
+
|
|
39
44
|
registerHandler('docHidden', msTimestamp => this.endCurrentSession(msTimestamp), this.featureName, this.ee)
|
|
40
45
|
// Add the time of _window pagehide event_ firing to the next PVT harvest == NRDB windowUnload attr:
|
|
41
46
|
registerHandler('winPagehide', msTimestamp => this.addTiming('unload', msTimestamp, null), this.featureName, this.ee)
|
|
@@ -141,7 +146,7 @@ export class Aggregate extends AggregateBase {
|
|
|
141
146
|
// serialize array of timing data
|
|
142
147
|
serializer (eventBuffer) {
|
|
143
148
|
if (!eventBuffer?.length) return ''
|
|
144
|
-
var addString = getAddStringContext(this.
|
|
149
|
+
var addString = getAddStringContext(this.obfuscator)
|
|
145
150
|
|
|
146
151
|
var payload = 'bel.6;'
|
|
147
152
|
|
|
@@ -19,17 +19,23 @@ import { stringify } from '../../../common/util/stringify'
|
|
|
19
19
|
import { stylesheetEvaluator } from '../shared/stylesheet-evaluator'
|
|
20
20
|
import { now } from '../../../common/timing/now'
|
|
21
21
|
import { MAX_PAYLOAD_SIZE } from '../../../common/constants/agent-constants'
|
|
22
|
+
import { EVENT_TYPES } from '../../../common/constants/events'
|
|
22
23
|
import { cleanURL } from '../../../common/url/clean-url'
|
|
23
24
|
import { canEnableSessionTracking } from '../../utils/feature-gates'
|
|
24
25
|
import { PAUSE_REPLAY } from '../../../loaders/api/constants'
|
|
26
|
+
import { Obfuscator } from '../../../common/util/obfuscate'
|
|
25
27
|
|
|
26
28
|
export class Aggregate extends AggregateBase {
|
|
27
29
|
static featureName = FEATURE_NAME
|
|
28
|
-
mode =
|
|
30
|
+
mode = null
|
|
29
31
|
|
|
30
32
|
// pass the recorder into the aggregator
|
|
31
33
|
constructor (agentRef, args) {
|
|
32
34
|
super(agentRef, FEATURE_NAME)
|
|
35
|
+
|
|
36
|
+
// Create obfuscator for session replay query params
|
|
37
|
+
this.obfuscator = new Obfuscator(agentRef, EVENT_TYPES.SR)
|
|
38
|
+
|
|
33
39
|
/** Set once the recorder has fully initialized after flag checks and sampling */
|
|
34
40
|
this.initialized = false
|
|
35
41
|
/** Set once the feature has been "aborted" to prevent other side-effects from continuing */
|
|
@@ -68,7 +74,7 @@ export class Aggregate extends AggregateBase {
|
|
|
68
74
|
if (!this.recorder) return
|
|
69
75
|
// if the mode changed on a different tab, it needs to update this instance to match
|
|
70
76
|
this.mode = agentRef.runtime.session.state.sessionReplayMode
|
|
71
|
-
if (!this.initialized || this.mode === MODE.OFF) return
|
|
77
|
+
if (!this.initialized || this.mode === MODE.OFF || !this.mode) return
|
|
72
78
|
this.recorder?.startRecording(TRIGGERS.RESUME, this.mode)
|
|
73
79
|
})
|
|
74
80
|
|
|
@@ -91,6 +97,8 @@ export class Aggregate extends AggregateBase {
|
|
|
91
97
|
this.waitForFlags(['srs', 'sr']).then(([srMode, entitled]) => {
|
|
92
98
|
this.entitled = !!entitled
|
|
93
99
|
if (!this.entitled) {
|
|
100
|
+
this.mode = MODE.OFF
|
|
101
|
+
this.#writeToStorage({ sessionReplayMode: this.mode })
|
|
94
102
|
this.deregisterDrain()
|
|
95
103
|
if (this.agentRef.runtime.isRecording) {
|
|
96
104
|
this.abort(ABORT_REASONS.ENTITLEMENTS)
|
|
@@ -100,7 +108,7 @@ export class Aggregate extends AggregateBase {
|
|
|
100
108
|
}
|
|
101
109
|
this.initializeRecording(srMode).then(() => { this.drain() })
|
|
102
110
|
}).then(() => {
|
|
103
|
-
if (this.mode
|
|
111
|
+
if (!this.mode) {
|
|
104
112
|
this.recorder?.stopRecording() // stop any conservative preload recording launched by instrument
|
|
105
113
|
while (this.recorder?.getEvents().events.length) this.recorder?.clearBuffer?.()
|
|
106
114
|
}
|
|
@@ -137,7 +145,7 @@ export class Aggregate extends AggregateBase {
|
|
|
137
145
|
// if the error was noticed AFTER the recorder was already imported....
|
|
138
146
|
if (this.recorder && this.initialized) {
|
|
139
147
|
if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(TRIGGERS.SWITCH_TO_FULL, this.mode) // off --> full
|
|
140
|
-
this
|
|
148
|
+
this.#writeToStorage({ sessionReplayMode: this.mode })
|
|
141
149
|
} else {
|
|
142
150
|
this.initializeRecording(MODE.FULL, true, TRIGGERS.SWITCH_TO_FULL)
|
|
143
151
|
}
|
|
@@ -165,35 +173,36 @@ export class Aggregate extends AggregateBase {
|
|
|
165
173
|
|
|
166
174
|
if (this.recorder?.trigger === TRIGGERS.API && this.agentRef.runtime.isRecording) {
|
|
167
175
|
this.mode = MODE.FULL
|
|
168
|
-
} else if (
|
|
176
|
+
} else if (session.state.sessionReplayMode !== null && !ignoreSession) { // inherit the mode of the existing session
|
|
169
177
|
this.mode = session.state.sessionReplayMode
|
|
170
178
|
} else {
|
|
171
179
|
// The session is new... determine the mode the new session should start in
|
|
172
180
|
this.mode = srMode
|
|
173
181
|
}
|
|
174
|
-
// If off, then don't record (early return)
|
|
175
|
-
if (this.mode === MODE.OFF) return
|
|
176
182
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// If an error was noticed before the mode could be set (like in the early lifecycle of the page), immediately set to FULL mode
|
|
186
|
-
if (this.mode === MODE.ERROR && this.instrumentClass.errorNoticed) { this.mode = MODE.FULL }
|
|
183
|
+
if (this.mode !== MODE.OFF) {
|
|
184
|
+
try {
|
|
185
|
+
/** will return a recorder instance if already imported, otherwise, will fetch the recorder and initialize it */
|
|
186
|
+
this.recorder ??= await this.instrumentClass.importRecorder()
|
|
187
|
+
} catch (err) {
|
|
188
|
+
/** if the recorder fails to import, abort the feature */
|
|
189
|
+
return this.abort(ABORT_REASONS.IMPORT, err)
|
|
190
|
+
}
|
|
187
191
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
// If an error was noticed before the mode could be set (like in the early lifecycle of the page), immediately set to FULL mode
|
|
193
|
+
if (this.mode === MODE.ERROR && this.instrumentClass.errorNoticed) {
|
|
194
|
+
this.mode = MODE.FULL
|
|
195
|
+
}
|
|
191
196
|
|
|
192
|
-
|
|
197
|
+
// FULL mode records AND reports from the beginning, while ERROR mode only records (but does not report).
|
|
198
|
+
// ERROR mode will do this until an error is thrown, and then switch into FULL mode.
|
|
199
|
+
// The makeHarvestPayload should ensure that no payload is returned if we're not in FULL mode...
|
|
193
200
|
|
|
194
|
-
|
|
201
|
+
await this.prepUtils()
|
|
195
202
|
|
|
196
|
-
|
|
203
|
+
if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(trigger, this.mode)
|
|
204
|
+
}
|
|
205
|
+
this.#writeToStorage({ sessionReplayMode: this.mode })
|
|
197
206
|
}
|
|
198
207
|
|
|
199
208
|
async prepUtils () {
|
|
@@ -240,7 +249,7 @@ export class Aggregate extends AggregateBase {
|
|
|
240
249
|
return
|
|
241
250
|
}
|
|
242
251
|
|
|
243
|
-
if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this
|
|
252
|
+
if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this.#writeToStorage({ sessionReplaySentFirstChunk: true })
|
|
244
253
|
this.recorder.clearBuffer()
|
|
245
254
|
|
|
246
255
|
if (!this.agentRef.runtime.session.state.traceHarvestStarted) {
|
|
@@ -303,7 +312,7 @@ export class Aggregate extends AggregateBase {
|
|
|
303
312
|
return {
|
|
304
313
|
qs: {
|
|
305
314
|
browser_monitoring_key: this.agentRef.info.licenseKey,
|
|
306
|
-
type:
|
|
315
|
+
type: EVENT_TYPES.SR,
|
|
307
316
|
app_id: this.agentRef.info.applicationID,
|
|
308
317
|
protocol_version: '0',
|
|
309
318
|
timestamp: firstTimestamp,
|
|
@@ -364,7 +373,7 @@ export class Aggregate extends AggregateBase {
|
|
|
364
373
|
if (forceHarvest) this.agentRef.runtime.harvester.triggerHarvestFor(this)
|
|
365
374
|
this.mode = MODE.OFF
|
|
366
375
|
this.recorder?.stopRecording?.()
|
|
367
|
-
this
|
|
376
|
+
this.#writeToStorage({ sessionReplayMode: this.mode })
|
|
368
377
|
}
|
|
369
378
|
|
|
370
379
|
/** Abort the feature, once aborted it will not resume */
|
|
@@ -374,12 +383,12 @@ export class Aggregate extends AggregateBase {
|
|
|
374
383
|
this.blocked = true
|
|
375
384
|
this.mode = MODE.OFF
|
|
376
385
|
this.recorder?.stopRecording?.()
|
|
377
|
-
this
|
|
386
|
+
this.#writeToStorage({ sessionReplayMode: this.mode })
|
|
378
387
|
this.recorder?.clearTimestamps?.()
|
|
379
388
|
while (this.recorder?.getEvents().events.length) this.recorder?.clearBuffer?.()
|
|
380
389
|
}
|
|
381
390
|
|
|
382
|
-
|
|
391
|
+
#writeToStorage (state = {}) {
|
|
383
392
|
if (this.isSessionTrackingEnabled) {
|
|
384
393
|
this.agentRef.runtime.session.write(state)
|
|
385
394
|
}
|