@newrelic/browser-agent 1.293.0-rc.3 → 1.293.0-rc.5
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/dist/cjs/common/aggregate/event-aggregator.js +3 -0
- package/dist/cjs/common/config/runtime.js +4 -0
- package/dist/cjs/common/constants/agent-constants.js +1 -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/event-emitter/contextual-ee.js +3 -2
- package/dist/cjs/common/util/attribute-size.js +31 -0
- package/dist/cjs/features/ajax/aggregate/index.js +6 -0
- package/dist/cjs/features/generic_events/aggregate/index.js +1 -14
- package/dist/cjs/features/generic_events/constants.js +1 -3
- package/dist/cjs/features/logging/aggregate/index.js +2 -23
- package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -0
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +4 -4
- package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +0 -4
- package/dist/cjs/features/soft_navigations/aggregate/index.js +12 -12
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +18 -11
- package/dist/cjs/features/utils/agent-session.js +13 -5
- package/dist/cjs/features/utils/aggregate-base.js +25 -2
- package/dist/cjs/features/utils/event-buffer.js +12 -3
- package/dist/cjs/features/utils/event-store-manager.js +6 -6
- package/dist/esm/common/aggregate/event-aggregator.js +3 -0
- package/dist/esm/common/config/runtime.js +4 -0
- package/dist/esm/common/constants/agent-constants.js +1 -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/event-emitter/contextual-ee.js +3 -2
- package/dist/esm/common/util/attribute-size.js +24 -0
- package/dist/esm/features/ajax/aggregate/index.js +6 -0
- package/dist/esm/features/generic_events/aggregate/index.js +1 -14
- package/dist/esm/features/generic_events/constants.js +0 -2
- package/dist/esm/features/logging/aggregate/index.js +2 -23
- package/dist/esm/features/page_view_timing/aggregate/index.js +2 -0
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +4 -4
- package/dist/esm/features/soft_navigations/aggregate/bel-node.js +0 -4
- package/dist/esm/features/soft_navigations/aggregate/index.js +12 -12
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +18 -11
- package/dist/esm/features/utils/agent-session.js +13 -5
- package/dist/esm/features/utils/aggregate-base.js +25 -2
- package/dist/esm/features/utils/event-buffer.js +12 -3
- package/dist/esm/features/utils/event-store-manager.js +7 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/aggregate/event-aggregator.d.ts +1 -0
- package/dist/types/common/aggregate/event-aggregator.d.ts.map +1 -1
- package/dist/types/common/config/runtime.d.ts.map +1 -1
- package/dist/types/common/constants/agent-constants.d.ts +1 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/util/attribute-size.d.ts +4 -0
- package/dist/types/common/util/attribute-size.d.ts.map +1 -0
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +0 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/constants.d.ts +0 -2
- package/dist/types/features/generic_events/constants.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +2 -2
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +0 -3
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +8 -2
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +10 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/event-buffer.d.ts +5 -2
- package/dist/types/features/utils/event-buffer.d.ts.map +1 -1
- package/dist/types/features/utils/event-store-manager.d.ts +3 -3
- package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/common/aggregate/event-aggregator.js +4 -0
- package/src/common/config/runtime.js +2 -0
- package/src/common/constants/agent-constants.js +1 -1
- package/src/common/event-emitter/contextual-ee.js +3 -2
- package/src/common/util/attribute-size.js +24 -0
- package/src/features/ajax/aggregate/index.js +7 -0
- package/src/features/generic_events/aggregate/index.js +1 -12
- package/src/features/generic_events/constants.js +0 -2
- package/src/features/logging/aggregate/index.js +3 -20
- package/src/features/page_view_timing/aggregate/index.js +3 -0
- package/src/features/soft_navigations/aggregate/ajax-node.js +4 -4
- package/src/features/soft_navigations/aggregate/bel-node.js +0 -5
- package/src/features/soft_navigations/aggregate/index.js +13 -10
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/src/features/soft_navigations/aggregate/interaction.js +14 -8
- package/src/features/utils/agent-session.js +13 -2
- package/src/features/utils/aggregate-base.js +22 -2
- package/src/features/utils/event-buffer.js +12 -3
- package/src/features/utils/event-store-manager.js +7 -7
|
@@ -31,8 +31,8 @@ export class Interaction extends BelNode {
|
|
|
31
31
|
onDone = []
|
|
32
32
|
cancellationTimer
|
|
33
33
|
|
|
34
|
-
constructor (
|
|
35
|
-
super(
|
|
34
|
+
constructor (uiEvent, uiEventTimestamp, currentRouteKnown, currentUrl) {
|
|
35
|
+
super()
|
|
36
36
|
this.belType = NODE_TYPE.INTERACTION
|
|
37
37
|
this.trigger = uiEvent
|
|
38
38
|
this.start = uiEventTimestamp
|
|
@@ -83,7 +83,6 @@ export class Interaction extends BelNode {
|
|
|
83
83
|
#finish (customEndTime = 0) {
|
|
84
84
|
clearTimeout(this.cancellationTimer)
|
|
85
85
|
this.end = Math.max(this.domTimestamp, this.historyTimestamp, customEndTime)
|
|
86
|
-
this.customAttributes = { ...this.info.jsAttributes, ...this.customAttributes } // attrs specific to this interaction should have precedence over the general custom attrs
|
|
87
86
|
this.status = INTERACTION_STATUS.FIN
|
|
88
87
|
|
|
89
88
|
// Run all the callbacks awaiting this interaction to finish.
|
|
@@ -116,9 +115,15 @@ export class Interaction extends BelNode {
|
|
|
116
115
|
get firstContentfulPaint () {}
|
|
117
116
|
get navTiming () {}
|
|
118
117
|
|
|
119
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Serializes (BEL) the interaction data for transmission.
|
|
120
|
+
* @param {Number} firstStartTimeOfPayload timestamp
|
|
121
|
+
* @param {Agent} agentRef Pass in the agent reference directly so that the event itself doesnt need to store the pointers and ruin the evaluation of the event size by including unused object references.
|
|
122
|
+
* @returns {String} A string that is the serialized representation of this interaction.
|
|
123
|
+
*/
|
|
124
|
+
serialize (firstStartTimeOfPayload, agentRef) {
|
|
120
125
|
const isFirstIxnOfPayload = firstStartTimeOfPayload === undefined
|
|
121
|
-
const addString = getAddStringContext(
|
|
126
|
+
const addString = getAddStringContext(agentRef.runtime.obfuscator)
|
|
122
127
|
const nodeList = []
|
|
123
128
|
let ixnType
|
|
124
129
|
if (this.trigger === IPL_TRIGGER_NAME) ixnType = INTERACTION_TYPE.INITIAL_PAGE_LOAD
|
|
@@ -145,12 +150,13 @@ export class Interaction extends BelNode {
|
|
|
145
150
|
addString(this.nodeId),
|
|
146
151
|
nullable(this.firstPaint, numeric, true) + nullable(this.firstContentfulPaint, numeric)
|
|
147
152
|
]
|
|
148
|
-
const
|
|
149
|
-
|
|
153
|
+
const customAttributes = { ...agentRef.info.jsAttributes, ...this.customAttributes } // attrs specific to this interaction should have precedence over the general custom attrs
|
|
154
|
+
const allAttachedNodes = addCustomAttributes(customAttributes || {}, addString) // start with all custom attributes
|
|
155
|
+
if (agentRef.info.atts) allAttachedNodes.push('a,' + addString(agentRef.info.atts)) // add apm provided attributes
|
|
150
156
|
/* Querypack encoder+decoder quirkiness:
|
|
151
157
|
- If first ixn node of payload is being processed, its children's start time must be offset by this node's start. (firstStartTime should be undefined.)
|
|
152
158
|
- Else for subsequent ixns in the same payload, we go back to using that first ixn node's start to offset their children's start. */
|
|
153
|
-
this.children.forEach(node => allAttachedNodes.push(node.serialize(isFirstIxnOfPayload ? this.start : firstStartTimeOfPayload))) // recursively add the serialized string of every child of this (ixn) bel node
|
|
159
|
+
this.children.forEach(node => allAttachedNodes.push(node.serialize(isFirstIxnOfPayload ? this.start : firstStartTimeOfPayload, agentRef))) // recursively add the serialized string of every child of this (ixn) bel node
|
|
154
160
|
|
|
155
161
|
fields[1] = numeric(allAttachedNodes.length)
|
|
156
162
|
nodeList.push(fields)
|
|
@@ -8,6 +8,8 @@ import { registerHandler } from '../../common/event-emitter/register-handler'
|
|
|
8
8
|
import { SessionEntity } from '../../common/session/session-entity'
|
|
9
9
|
import { LocalStorage } from '../../common/storage/local-storage.js'
|
|
10
10
|
import { DEFAULT_KEY } from '../../common/session/constants'
|
|
11
|
+
import { mergeInfo } from '../../common/config/info'
|
|
12
|
+
import { trackObjectAttributeSize } from '../../common/util/attribute-size'
|
|
11
13
|
|
|
12
14
|
export function setupAgentSession (agentRef) {
|
|
13
15
|
if (agentRef.runtime.session) return agentRef.runtime.session // already setup
|
|
@@ -24,11 +26,20 @@ export function setupAgentSession (agentRef) {
|
|
|
24
26
|
|
|
25
27
|
// Retrieve & re-add all of the persisted setCustomAttribute|setUserId k-v from previous page load(s), if any was stored.
|
|
26
28
|
const customSessionData = agentRef.runtime.session.state.custom
|
|
27
|
-
if (customSessionData) {
|
|
29
|
+
if (customSessionData && Object.keys(customSessionData).length) {
|
|
28
30
|
/** stored attributes from previous page should not take precedence over attributes stored on this page via API before the page load */
|
|
29
|
-
agentRef.info
|
|
31
|
+
agentRef.info = mergeInfo({
|
|
32
|
+
...agentRef.info,
|
|
33
|
+
jsAttributes: {
|
|
34
|
+
...customSessionData,
|
|
35
|
+
...agentRef.info.jsAttributes
|
|
36
|
+
}
|
|
37
|
+
})
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
/** track changes to the jsAttributes field over time for aiding with harvest mechanics */
|
|
41
|
+
agentRef.runtime.jsAttributesMetadata = trackObjectAttributeSize(agentRef.info, 'jsAttributes')
|
|
42
|
+
|
|
32
43
|
const sharedEE = ee.get(agentRef.agentIdentifier)
|
|
33
44
|
|
|
34
45
|
// any calls to newrelic.setCustomAttribute(<persisted>) will need to be added to:
|
|
@@ -18,6 +18,7 @@ import { EventBuffer } from './event-buffer'
|
|
|
18
18
|
import { handle } from '../../common/event-emitter/handle'
|
|
19
19
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../metrics/constants'
|
|
20
20
|
import { EventAggregator } from '../../common/aggregate/event-aggregator'
|
|
21
|
+
import { IDEAL_PAYLOAD_SIZE } from '../../common/constants/agent-constants'
|
|
21
22
|
|
|
22
23
|
export class AggregateBase extends FeatureBase {
|
|
23
24
|
/**
|
|
@@ -31,6 +32,11 @@ export class AggregateBase extends FeatureBase {
|
|
|
31
32
|
this.checkConfiguration(agentRef)
|
|
32
33
|
this.doOnceForAllAggregate(agentRef)
|
|
33
34
|
|
|
35
|
+
/** @type {Boolean} indicates if custom attributes are combined in each event payload for size estimation purposes. this is set to true in derived classes that need to evaluate custom attributes separately from the event payload */
|
|
36
|
+
this.customAttributesAreSeparate = false
|
|
37
|
+
/** @type {Boolean} indicates if the feature can harvest early. This is set to false in derived classes that need to block early harvests, like ajax under certain conditions */
|
|
38
|
+
this.canHarvestEarly = true // this is set to false in derived classes that need to block early harvests, like ajax under certain conditions
|
|
39
|
+
|
|
34
40
|
this.harvestOpts = {} // features aggregate classes can define custom opts for when their harvest is called
|
|
35
41
|
|
|
36
42
|
const agentEntityGuid = this.agentRef?.runtime?.appMetadata?.agents?.[0]?.entityGuid
|
|
@@ -60,17 +66,31 @@ export class AggregateBase extends FeatureBase {
|
|
|
60
66
|
// Jserror and Metric features uses a singleton EventAggregator instead of a regular EventBuffer.
|
|
61
67
|
case FEATURE_NAMES.jserrors:
|
|
62
68
|
case FEATURE_NAMES.metrics:
|
|
63
|
-
this.events = this.agentRef.sharedAggregator ??= new EventStoreManager(this.agentRef, EventAggregator, entityGuid, 'shared_aggregator')
|
|
69
|
+
this.events = this.agentRef.sharedAggregator ??= new EventStoreManager(this.agentRef, EventAggregator, entityGuid, { featureName: 'shared_aggregator' })
|
|
64
70
|
break
|
|
65
71
|
/** All other features get EventBuffer in the ESM by default. Note: PVE is included here, but event buffer will always be empty so future harvests will still not happen by interval or EOL.
|
|
66
72
|
This was necessary to prevent race cond. issues where the event buffer was checked before the feature could "block" itself.
|
|
67
73
|
Its easier to just keep an empty event buffer in place. */
|
|
68
74
|
default:
|
|
69
|
-
this.events = new EventStoreManager(this.agentRef, EventBuffer, entityGuid, this
|
|
75
|
+
this.events = new EventStoreManager(this.agentRef, EventBuffer, entityGuid, this)
|
|
70
76
|
break
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Evaluates whether a harvest should be made early by estimating the size of the current payload. Currently, this only happens if the event storage is EventBuffer, since that triggers this method directly.
|
|
82
|
+
* If conditions are met, a new harvest will be triggered immediately.
|
|
83
|
+
* @returns void
|
|
84
|
+
*/
|
|
85
|
+
decideEarlyHarvest () {
|
|
86
|
+
if (!this.canHarvestEarly) return
|
|
87
|
+
const estimatedSize = this.events.byteSize() + (this.customAttributesAreSeparate ? this.agentRef.runtime.jsAttributesMetadata.bytes : 0)
|
|
88
|
+
if (estimatedSize > IDEAL_PAYLOAD_SIZE) {
|
|
89
|
+
this.agentRef.runtime.harvester.triggerHarvestFor(this)
|
|
90
|
+
this.reportSupportabilityMetric(`${this.featureName}/Harvest/Early/Seen`, estimatedSize)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
/**
|
|
75
95
|
* New handler for waiting for multiple flags. Useful when expecting multiple flags simultaneously (ex. stn vs sr)
|
|
76
96
|
* @param {string[]} flagNames
|
|
@@ -12,10 +12,13 @@ export class EventBuffer {
|
|
|
12
12
|
#rawBytesBackup
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Creates an event buffer that can hold feature-processed events.
|
|
16
|
+
* @param {Number} maxPayloadSize The maximum size of the payload that can be stored in this buffer.
|
|
17
|
+
* @param {Object} [featureAgg] - the feature aggregate instance
|
|
16
18
|
*/
|
|
17
|
-
constructor (maxPayloadSize = MAX_PAYLOAD_SIZE) {
|
|
19
|
+
constructor (maxPayloadSize = MAX_PAYLOAD_SIZE, featureAgg) {
|
|
18
20
|
this.maxPayloadSize = maxPayloadSize
|
|
21
|
+
this.featureAgg = featureAgg
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
isEmpty () {
|
|
@@ -41,9 +44,15 @@ export class EventBuffer {
|
|
|
41
44
|
*/
|
|
42
45
|
add (event) {
|
|
43
46
|
const addSize = stringify(event)?.length || 0 // (estimate) # of bytes a directly stringified event it would take to send
|
|
44
|
-
if (this.#rawBytes + addSize > this.maxPayloadSize)
|
|
47
|
+
if (this.#rawBytes + addSize > this.maxPayloadSize) {
|
|
48
|
+
const smTag = inject => `EventBuffer/${inject}/Dropped/Bytes`
|
|
49
|
+
this.featureAgg?.reportSupportabilityMetric(smTag(this.featureAgg.featureName), addSize) // bytes dropped for this feature will aggregate with this metric tag
|
|
50
|
+
this.featureAgg?.reportSupportabilityMetric(smTag('Combined'), addSize) // all bytes dropped across all features will aggregate with this metric tag
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
45
53
|
this.#buffer.push(event)
|
|
46
54
|
this.#rawBytes += addSize
|
|
55
|
+
this.featureAgg?.decideEarlyHarvest() // check if we should harvest early with new data
|
|
47
56
|
return true
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { DEFAULT_KEY } from '../../common/constants/agent-constants'
|
|
5
|
+
import { DEFAULT_KEY, MAX_PAYLOAD_SIZE } from '../../common/constants/agent-constants'
|
|
6
6
|
import { dispatchGlobalEvent } from '../../common/dispatch/global-event'
|
|
7
7
|
import { activatedFeatures } from '../../common/util/feature-flags'
|
|
8
8
|
import { isContainerAgentTarget } from '../../common/util/target'
|
|
@@ -15,14 +15,14 @@ export class EventStoreManager {
|
|
|
15
15
|
* @param {object} agentRef - reference to base agent class
|
|
16
16
|
* @param {EventBuffer|EventAggregator} storageClass - the type of storage to use in this manager; 'EventBuffer' (1), 'EventAggregator' (2)
|
|
17
17
|
* @param {string} [defaultEntityGuid] - the entity guid to use as the default storage instance; if not provided, a new one is created
|
|
18
|
-
* @param {
|
|
18
|
+
* @param {Object} featureAgg - the feature aggregate instance that initialized this manager
|
|
19
19
|
*/
|
|
20
|
-
constructor (agentRef, storageClass, defaultEntityGuid,
|
|
20
|
+
constructor (agentRef, storageClass, defaultEntityGuid, featureAgg) {
|
|
21
21
|
this.agentRef = agentRef
|
|
22
22
|
this.entityManager = agentRef.runtime.entityManager
|
|
23
23
|
this.StorageClass = storageClass
|
|
24
|
-
this.appStorageMap = new Map([[DEFAULT_KEY, new this.StorageClass()]])
|
|
25
|
-
this.
|
|
24
|
+
this.appStorageMap = new Map([[DEFAULT_KEY, new this.StorageClass(MAX_PAYLOAD_SIZE, featureAgg)]])
|
|
25
|
+
this.featureAgg = featureAgg
|
|
26
26
|
this.setEventStore(defaultEntityGuid)
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -42,7 +42,7 @@ export class EventStoreManager {
|
|
|
42
42
|
/** if the target is the container agent, SHARE the default storage -- otherwise create a new event store */
|
|
43
43
|
const eventStorage = (isContainerAgentTarget(this.entityManager.get(targetEntityGuid), this.agentRef))
|
|
44
44
|
? this.appStorageMap.get(DEFAULT_KEY)
|
|
45
|
-
: new this.StorageClass()
|
|
45
|
+
: new this.StorageClass(MAX_PAYLOAD_SIZE, this.featureAgg)
|
|
46
46
|
this.appStorageMap.set(targetEntityGuid, eventStorage)
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -75,7 +75,7 @@ export class EventStoreManager {
|
|
|
75
75
|
drained: !!activatedFeatures?.[this.agentRef.agentIdentifier],
|
|
76
76
|
type: 'data',
|
|
77
77
|
name: 'buffer',
|
|
78
|
-
feature: this.featureName,
|
|
78
|
+
feature: this.featureAgg.featureName,
|
|
79
79
|
data: event
|
|
80
80
|
})
|
|
81
81
|
return this.#getEventStore(targetEntityGuid).add(event)
|