@newrelic/browser-agent 1.313.1 → 1.314.0-rc.1
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 +11 -0
- package/dist/cjs/common/constants/agent-constants.js +2 -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/dom/selector-path.js +12 -3
- package/dist/cjs/common/timing/time-keeper.js +18 -6
- package/dist/cjs/common/vitals/cumulative-layout-shift.js +3 -2
- package/dist/cjs/common/vitals/interaction-to-next-paint.js +3 -2
- package/dist/cjs/common/vitals/largest-contentful-paint.js +2 -1
- package/dist/cjs/common/vitals/load-time.js +5 -2
- package/dist/cjs/common/vitals/vital-metric.js +7 -4
- package/dist/cjs/features/ajax/aggregate/index.js +6 -2
- package/dist/cjs/features/ajax/constants.js +4 -3
- package/dist/cjs/features/generic_events/aggregate/index.js +60 -53
- package/dist/cjs/features/generic_events/aggregate/user-actions/aggregated-user-action.js +2 -1
- package/dist/cjs/features/generic_events/aggregate/user-actions/user-actions-aggregator.js +4 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +27 -6
- package/dist/cjs/features/session_replay/aggregate/index.js +15 -6
- package/dist/cjs/features/session_replay/constants.js +1 -1
- package/dist/cjs/features/session_replay/shared/recorder.js +3 -1
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +7 -3
- package/dist/esm/common/constants/agent-constants.js +2 -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/dom/selector-path.js +13 -3
- package/dist/esm/common/timing/time-keeper.js +18 -6
- package/dist/esm/common/vitals/cumulative-layout-shift.js +3 -2
- package/dist/esm/common/vitals/interaction-to-next-paint.js +3 -2
- package/dist/esm/common/vitals/largest-contentful-paint.js +2 -1
- package/dist/esm/common/vitals/load-time.js +5 -2
- package/dist/esm/common/vitals/vital-metric.js +7 -4
- package/dist/esm/features/ajax/aggregate/index.js +7 -3
- package/dist/esm/features/ajax/constants.js +3 -2
- package/dist/esm/features/generic_events/aggregate/index.js +61 -54
- package/dist/esm/features/generic_events/aggregate/user-actions/aggregated-user-action.js +2 -1
- package/dist/esm/features/generic_events/aggregate/user-actions/user-actions-aggregator.js +4 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +27 -6
- package/dist/esm/features/session_replay/aggregate/index.js +15 -6
- package/dist/esm/features/session_replay/constants.js +1 -1
- package/dist/esm/features/session_replay/shared/recorder.js +3 -1
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +5 -1
- package/dist/types/common/constants/agent-constants.d.ts +1 -0
- package/dist/types/common/constants/agent-constants.d.ts.map +1 -1
- package/dist/types/common/dom/selector-path.d.ts +2 -1
- package/dist/types/common/dom/selector-path.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
- package/dist/types/common/vitals/vital-metric.d.ts +3 -2
- package/dist/types/common/vitals/vital-metric.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.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/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/user-actions/aggregated-user-action.d.ts +1 -0
- package/dist/types/features/generic_events/aggregate/user-actions/aggregated-user-action.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/user-actions/user-actions-aggregator.d.ts +2 -0
- package/dist/types/features/generic_events/aggregate/user-actions/user-actions-aggregator.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +1 -11
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts +2 -0
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +1 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/common/constants/agent-constants.js +2 -1
- package/src/common/dom/selector-path.js +13 -4
- package/src/common/timing/time-keeper.js +17 -6
- package/src/common/vitals/cumulative-layout-shift.js +2 -2
- package/src/common/vitals/interaction-to-next-paint.js +2 -2
- package/src/common/vitals/largest-contentful-paint.js +1 -1
- package/src/common/vitals/load-time.js +5 -2
- package/src/common/vitals/vital-metric.js +6 -4
- package/src/features/ajax/aggregate/index.js +6 -3
- package/src/features/ajax/constants.js +3 -1
- package/src/features/generic_events/aggregate/index.js +42 -39
- package/src/features/generic_events/aggregate/user-actions/aggregated-user-action.js +2 -1
- package/src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js +4 -3
- package/src/features/page_view_timing/aggregate/index.js +14 -6
- package/src/features/session_replay/aggregate/index.js +16 -5
- package/src/features/session_replay/constants.js +1 -1
- package/src/features/session_replay/shared/recorder.js +3 -1
- package/src/features/soft_navigations/aggregate/ajax-node.js +4 -1
|
@@ -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 { RAGE_CLICK_THRESHOLD_EVENTS, RAGE_CLICK_THRESHOLD_MS } from '../../constants'
|
|
@@ -17,6 +17,7 @@ export class AggregatedUserAction {
|
|
|
17
17
|
this.currentUrl = cleanURL('' + location)
|
|
18
18
|
this.deadClick = false
|
|
19
19
|
this.errorClick = false
|
|
20
|
+
this.targets = selectorInfo.targets
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -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 { analyzeElemPath } from '../../../../common/dom/selector-path'
|
|
@@ -16,7 +16,8 @@ export class UserActionsAggregator {
|
|
|
16
16
|
#domObserver = undefined
|
|
17
17
|
#errorClickTimer = undefined
|
|
18
18
|
|
|
19
|
-
constructor () {
|
|
19
|
+
constructor (agentRef) {
|
|
20
|
+
this.agentRef = agentRef
|
|
20
21
|
if (gosNREUMOriginals().o.MO) {
|
|
21
22
|
this.#domObserver = new MutationObserver(this.isLiveClick.bind(this))
|
|
22
23
|
}
|
|
@@ -40,7 +41,7 @@ export class UserActionsAggregator {
|
|
|
40
41
|
process (evt, targetFields) {
|
|
41
42
|
if (!evt) return
|
|
42
43
|
const targetElem = OBSERVED_WINDOW_EVENTS.includes(evt.type) ? window : evt.target
|
|
43
|
-
const selectorInfo = analyzeElemPath(targetElem, targetFields)
|
|
44
|
+
const selectorInfo = analyzeElemPath(targetElem, targetFields, this.agentRef)
|
|
44
45
|
|
|
45
46
|
// if selectorInfo.path is undefined, aggregation will be skipped for this event
|
|
46
47
|
const aggregationKey = getAggregationKey(evt, selectorInfo.path)
|
|
@@ -20,13 +20,15 @@ import { initiallyHidden, getNavigationEntry, initialLocation } from '../../../c
|
|
|
20
20
|
import { eventOrigin } from '../../../common/util/event-origin'
|
|
21
21
|
import { loadTime } from '../../../common/vitals/load-time'
|
|
22
22
|
import { webdriverDetected } from '../../../common/util/webdriver-detection'
|
|
23
|
+
import { analyzeElemPath } from '../../../common/dom/selector-path'
|
|
24
|
+
import { getVersion2Attributes, getVersion2DuplicationAttributes, shouldDuplicate } from '../../../common/v2/utils'
|
|
23
25
|
import { cleanURL } from '../../../common/url/clean-url'
|
|
24
26
|
|
|
25
27
|
export class Aggregate extends AggregateBase {
|
|
26
28
|
static featureName = FEATURE_NAME
|
|
27
29
|
|
|
28
|
-
#handleVitalMetric = ({ name, value, attrs }) => {
|
|
29
|
-
this.addTiming(name, value, attrs)
|
|
30
|
+
#handleVitalMetric = ({ name, value, attrs, element }) => {
|
|
31
|
+
this.addTiming(name, value, attrs, element)
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
constructor (agentRef) {
|
|
@@ -50,9 +52,9 @@ export class Aggregate extends AggregateBase {
|
|
|
50
52
|
/* Downstream, the event consumer interprets all timing node value as ms-unit and converts it to seconds via division by 1000. CLS is unitless so this normally is a problem.
|
|
51
53
|
bel.6 schema also doesn't support decimal values, of which cls within [0,1). However, the two nicely cancels out, and we can multiply cls by 1000 to both negate the division
|
|
52
54
|
and send an integer > 1. We effectively lose some precision down to 3 decimal places for this workaround. E.g. (real) 0.749132... -> 749.132...-> 749 -> 0.749 (final) */
|
|
53
|
-
const { name, value, attrs } = cumulativeLayoutShift.current
|
|
55
|
+
const { name, value, attrs, element } = cumulativeLayoutShift.current
|
|
54
56
|
if (value === undefined) return
|
|
55
|
-
this.addTiming(name, value * 1000, attrs)
|
|
57
|
+
this.addTiming(name, value * 1000, attrs, element)
|
|
56
58
|
}, true, true) // CLS node should only reports on vis change rather than on every change
|
|
57
59
|
|
|
58
60
|
this.drain()
|
|
@@ -70,7 +72,7 @@ export class Aggregate extends AggregateBase {
|
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
addTiming (name, value, attrs) {
|
|
75
|
+
addTiming (name, value, attrs, element) {
|
|
74
76
|
attrs = attrs || {}
|
|
75
77
|
attrs.pageUrl = cleanURL(getNavigationEntry()?.name || initialLocation)
|
|
76
78
|
|
|
@@ -93,7 +95,13 @@ export class Aggregate extends AggregateBase {
|
|
|
93
95
|
value,
|
|
94
96
|
attrs
|
|
95
97
|
}
|
|
96
|
-
|
|
98
|
+
|
|
99
|
+
const targets = analyzeElemPath(element, [], this.agentRef).targets
|
|
100
|
+
if (!targets.length) targets.push(undefined)
|
|
101
|
+
targets.forEach(target => {
|
|
102
|
+
this.events.add({ ...timing, attrs: { ...attrs, ...getVersion2Attributes(target, this) } })
|
|
103
|
+
if (shouldDuplicate(target, this.agentRef)) this.events.add({ ...timing, attrs: { ...attrs, ...getVersion2DuplicationAttributes(target, this) } })
|
|
104
|
+
})
|
|
97
105
|
|
|
98
106
|
handle('pvtAdded', [name, value, attrs], undefined, FEATURE_NAMES.sessionTrace, this.ee)
|
|
99
107
|
|
|
@@ -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
|
/**
|
|
@@ -209,6 +209,7 @@ export class Aggregate extends AggregateBase {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
makeHarvestPayload () {
|
|
212
|
+
if (this.isRetrying) return this.recorder.retryPayload
|
|
212
213
|
if (this.mode !== MODE.FULL || this.blocked) return // harvests should only be made in FULL mode, and not if the feature is blocked
|
|
213
214
|
if (this.shouldCompress && !this.gzipper) return // if compression is enabled, but the libraries have not loaded, wait for them to load
|
|
214
215
|
if (!this.recorder || !this.timeKeeper?.ready || !(this.recorder.hasSeenSnapshot && this.recorder.hasSeenMeta)) return // if the recorder or the timekeeper is not ready, or the recorder has not yet seen a snapshot, do not harvest
|
|
@@ -239,7 +240,6 @@ export class Aggregate extends AggregateBase {
|
|
|
239
240
|
return
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
// TODO -- Gracefully handle the buffer for retries.
|
|
243
243
|
if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this.syncWithSessionManager({ sessionReplaySentFirstChunk: true })
|
|
244
244
|
this.recorder.clearBuffer()
|
|
245
245
|
|
|
@@ -247,6 +247,8 @@ export class Aggregate extends AggregateBase {
|
|
|
247
247
|
warn(59, JSON.stringify(this.agentRef.runtime.session.state))
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
this.recorder.retryPayload = payload
|
|
251
|
+
|
|
250
252
|
return payload
|
|
251
253
|
}
|
|
252
254
|
|
|
@@ -338,9 +340,18 @@ export class Aggregate extends AggregateBase {
|
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
postHarvestCleanup (result) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
343
|
+
if (result.sent) {
|
|
344
|
+
if (result.retry) {
|
|
345
|
+
warn(70)
|
|
346
|
+
this.isRetrying = true
|
|
347
|
+
this.forceStop()
|
|
348
|
+
} else {
|
|
349
|
+
this.recorder.retryPayload = undefined
|
|
350
|
+
if (this.isRetrying) {
|
|
351
|
+
this.isRetrying = false
|
|
352
|
+
this.switchToFull()
|
|
353
|
+
}
|
|
354
|
+
}
|
|
344
355
|
}
|
|
345
356
|
}
|
|
346
357
|
|
|
@@ -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 { record as recorder } from '@newrelic/rrweb'
|
|
@@ -45,6 +45,8 @@ export class Recorder {
|
|
|
45
45
|
this.events = new RecorderEvents(this.shouldFix)
|
|
46
46
|
/** Backlog used for a 2-part sliding window to guarantee a 15-30s buffer window */
|
|
47
47
|
this.backloggedEvents = new RecorderEvents(this.shouldFix)
|
|
48
|
+
/** Used to hold the harvest contents to facilitate retrying */
|
|
49
|
+
this.retryPayload = undefined
|
|
48
50
|
/** Only set to true once a snapshot node has been processed. Used to block harvests from sending before we know we have a snapshot */
|
|
49
51
|
this.hasSeenSnapshot = false
|
|
50
52
|
this.hasSeenMeta = false
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { addCustomAttributes, getAddStringContext, nullable, numeric } from '../../../common/serialize/bel-serializer'
|
|
6
|
+
import { AJAX_ID } from '../../ajax/constants'
|
|
6
7
|
import { NODE_TYPE } from '../constants'
|
|
7
8
|
import { BelNode } from './bel-node'
|
|
8
9
|
|
|
@@ -22,6 +23,7 @@ export class AjaxNode extends BelNode {
|
|
|
22
23
|
this.spanTimestamp = ajaxEvent.spanTimestamp
|
|
23
24
|
this.gql = ajaxEvent.gql
|
|
24
25
|
this.targetAttributes = ajaxEvent.targetAttributes
|
|
26
|
+
this[AJAX_ID] = ajaxEvent[AJAX_ID] // all AjaxRequest events should have a unique identifier to allow for easier grouping and analysis in the UI
|
|
25
27
|
|
|
26
28
|
this.start = ajaxEvent.startTime
|
|
27
29
|
this.end = ajaxEvent.endTime
|
|
@@ -55,7 +57,8 @@ export class AjaxNode extends BelNode {
|
|
|
55
57
|
]
|
|
56
58
|
let allAttachedNodes = addCustomAttributes({
|
|
57
59
|
...(this.gql || {}),
|
|
58
|
-
...(this.targetAttributes || {})
|
|
60
|
+
...(this.targetAttributes || {}),
|
|
61
|
+
[AJAX_ID]: this[AJAX_ID]
|
|
59
62
|
}, addString)
|
|
60
63
|
this.children.forEach(node => allAttachedNodes.push(node.serialize())) // no children is expected under ajax nodes at this time
|
|
61
64
|
|