@newrelic/browser-agent 1.302.0 → 1.303.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 +20 -0
- package/dist/cjs/common/config/init-types.js +2 -0
- package/dist/cjs/common/config/init.js +3 -0
- package/dist/cjs/common/config/runtime.js +9 -0
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +13 -9
- package/dist/cjs/common/harvest/types.js +0 -1
- package/dist/cjs/common/session/session-entity.js +4 -2
- package/dist/cjs/common/util/mfe.js +8 -5
- package/dist/cjs/common/wrap/wrap-promise.js +10 -5
- package/dist/cjs/features/generic_events/aggregate/index.js +4 -4
- package/dist/cjs/features/logging/aggregate/index.js +1 -2
- package/dist/cjs/features/page_view_event/aggregate/index.js +84 -22
- package/dist/cjs/features/page_view_event/instrument/index.js +0 -4
- package/dist/cjs/features/session_replay/aggregate/index.js +3 -2
- package/dist/cjs/features/session_replay/constants.js +2 -6
- package/dist/cjs/features/session_replay/instrument/index.js +3 -2
- package/dist/cjs/features/utils/agent-session.js +5 -0
- package/dist/cjs/features/utils/instrument-base.js +7 -8
- package/dist/cjs/interfaces/registered-entity.js +21 -0
- package/dist/cjs/loaders/agent.js +2 -0
- package/dist/cjs/loaders/api/consent.js +37 -0
- package/dist/cjs/loaders/api/constants.js +3 -2
- package/dist/cjs/loaders/api/measure.js +36 -35
- package/dist/cjs/loaders/api/recordCustomEvent.js +5 -3
- package/dist/cjs/loaders/api/register-api-types.js +14 -10
- package/dist/cjs/loaders/api/register.js +25 -10
- package/dist/cjs/loaders/api-base.js +14 -7
- package/dist/esm/common/config/init-types.js +2 -0
- package/dist/esm/common/config/init.js +3 -0
- package/dist/esm/common/config/runtime.js +9 -0
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvester.js +13 -9
- package/dist/esm/common/harvest/types.js +0 -1
- package/dist/esm/common/session/session-entity.js +4 -2
- package/dist/esm/common/util/mfe.js +7 -5
- package/dist/esm/common/wrap/wrap-promise.js +10 -5
- package/dist/esm/features/generic_events/aggregate/index.js +4 -4
- package/dist/esm/features/logging/aggregate/index.js +1 -2
- package/dist/esm/features/page_view_event/aggregate/index.js +84 -22
- package/dist/esm/features/page_view_event/instrument/index.js +0 -4
- package/dist/esm/features/session_replay/aggregate/index.js +4 -3
- package/dist/esm/features/session_replay/constants.js +1 -5
- package/dist/esm/features/session_replay/instrument/index.js +4 -3
- package/dist/esm/features/utils/agent-session.js +5 -0
- package/dist/esm/features/utils/instrument-base.js +7 -8
- package/dist/esm/interfaces/registered-entity.js +21 -0
- package/dist/esm/loaders/agent.js +2 -0
- package/dist/esm/loaders/api/consent.js +30 -0
- package/dist/esm/loaders/api/constants.js +2 -1
- package/dist/esm/loaders/api/measure.js +35 -35
- package/dist/esm/loaders/api/recordCustomEvent.js +4 -3
- package/dist/esm/loaders/api/register-api-types.js +14 -10
- package/dist/esm/loaders/api/register.js +26 -10
- package/dist/esm/loaders/api-base.js +15 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +6 -0
- package/dist/types/common/config/init.d.ts.map +1 -1
- package/dist/types/common/config/runtime.d.ts.map +1 -1
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/harvest/types.d.ts +0 -2
- package/dist/types/common/harvest/types.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/util/mfe.d.ts +3 -0
- package/dist/types/common/util/mfe.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +22 -3
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/constants.d.ts +1 -5
- package/dist/types/features/session_replay/constants.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +1 -0
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/interfaces/registered-entity.d.ts +25 -0
- package/dist/types/interfaces/registered-entity.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/consent.d.ts +2 -0
- package/dist/types/loaders/api/consent.d.ts.map +1 -0
- package/dist/types/loaders/api/constants.d.ts +1 -0
- package/dist/types/loaders/api/constants.d.ts.map +1 -1
- package/dist/types/loaders/api/measure.d.ts +3 -0
- package/dist/types/loaders/api/measure.d.ts.map +1 -1
- package/dist/types/loaders/api/recordCustomEvent.d.ts +1 -0
- package/dist/types/loaders/api/recordCustomEvent.d.ts.map +1 -1
- package/dist/types/loaders/api/register-api-types.d.ts +43 -12
- package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
- package/dist/types/loaders/api/register.d.ts +0 -16
- package/dist/types/loaders/api/register.d.ts.map +1 -1
- package/dist/types/loaders/api-base.d.ts +20 -15
- package/dist/types/loaders/api-base.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/common/config/init-types.js +2 -0
- package/src/common/config/init.js +1 -0
- package/src/common/config/runtime.js +10 -0
- package/src/common/harvest/harvester.js +11 -8
- package/src/common/harvest/types.js +0 -1
- package/src/common/session/session-entity.js +6 -2
- package/src/common/util/mfe.js +10 -4
- package/src/common/wrap/wrap-promise.js +16 -6
- package/src/features/generic_events/aggregate/index.js +4 -4
- package/src/features/logging/aggregate/index.js +1 -1
- package/src/features/page_view_event/aggregate/index.js +79 -15
- package/src/features/page_view_event/instrument/index.js +0 -4
- package/src/features/session_replay/aggregate/index.js +4 -3
- package/src/features/session_replay/constants.js +1 -5
- package/src/features/session_replay/instrument/index.js +4 -3
- package/src/features/utils/agent-session.js +4 -0
- package/src/features/utils/instrument-base.js +7 -9
- package/src/interfaces/registered-entity.js +21 -0
- package/src/loaders/agent.js +2 -0
- package/src/loaders/api/consent.js +31 -0
- package/src/loaders/api/constants.js +1 -0
- package/src/loaders/api/measure.js +34 -33
- package/src/loaders/api/recordCustomEvent.js +5 -3
- package/src/loaders/api/register-api-types.js +14 -10
- package/src/loaders/api/register.js +17 -10
- package/src/loaders/api-base.js +15 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/api-base.js"],"names":[],"mappings":"AAOA;;GAEG;AACH;IAQE;;;;;OAKG;IACH,oBAHW,MAAM,eACN,MAAM,OAIhB;IAED
|
|
1
|
+
{"version":3,"file":"api-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/api-base.js"],"names":[],"mappings":"AAOA;;GAEG;AACH;IAQE;;;;;OAKG;IACH,oBAHW,MAAM,eACN,MAAM,OAIhB;IAED;;;;;;;;OAQG;IACH,iBAHW,OAAO,0BAA0B,EAAE,sBAAsB,GAC1D,OAAO,0BAA0B,EAAE,WAAW,CAIvD;IAED;;;;;OAKG;IACH,6BAHW,MAAM,eACN,MAAM,OAIhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,SACN,MAAM,OAIhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,YAC1B,OAAO,OAIjB;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,qBACZ,MAAM,OAIhB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;;MAKE;IACF,aAHW,MAAM,YACN;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM,CAAA;KAAC,OAIpF;IAED;;;OAGG;IACH,aAEC;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAIhB;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;;OAKG;IACH,mBAEC;IAED;;;;;;;;;;OAUG;IACH,6BARW;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,OAUrF;IAED;;;;;OAKG;IACH,0BAHW,MAAM,OAKhB;IAED;;;;;;;;MAQE;IACF,mBALG;QAAuB,UAAU;KACjC,GAAU,mBAAmB,CAM/B;IAED;;;;;;MAME;IACF,mBAJW,MAAM,gBACN,MAAM,YACN;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM,CAAA;KAAC,OAIpF;IAED;;;;;;OAMG;IACH,cAJW,MAAM,YACN;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAC,GACtE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAC,CAIpF;IAED;;;;;OAKG;IACH,gBAFW,OAAO,OAAC,OAIlB;;CACF;kCArOY,OAAO,yBAAyB,EAAE,mBAAmB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/browser-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.303.0-rc.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
|
|
6
6
|
"description": "New Relic Browser Agent",
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
"runtime": {
|
|
171
171
|
"name": "node",
|
|
172
172
|
"onFail": "error",
|
|
173
|
-
"version": "22.11.0"
|
|
173
|
+
"version": ">=22.11.0"
|
|
174
174
|
},
|
|
175
175
|
"packageManager": {
|
|
176
176
|
"name": "npm",
|
|
@@ -220,8 +220,8 @@
|
|
|
220
220
|
"url": "https://github.com/newrelic/newrelic-browser-agent.git"
|
|
221
221
|
},
|
|
222
222
|
"dependencies": {
|
|
223
|
-
"fflate": "0.8.2",
|
|
224
223
|
"@newrelic/rrweb": "1.0.1",
|
|
224
|
+
"fflate": "0.8.2",
|
|
225
225
|
"web-vitals": "4.2.4"
|
|
226
226
|
},
|
|
227
227
|
"devDependencies": {
|
|
@@ -291,4 +291,4 @@
|
|
|
291
291
|
"README.md",
|
|
292
292
|
"CHANGELOG.md"
|
|
293
293
|
]
|
|
294
|
-
}
|
|
294
|
+
}
|
|
@@ -84,6 +84,8 @@
|
|
|
84
84
|
* @property {boolean} [spa.enabled] - Turn on/off the single page application feature (on by default). NOTE: the SPA feature is deprecated and under removal procedure.
|
|
85
85
|
* @property {boolean} [spa.autoStart] - If true, the agent will automatically start the single page application feature. Otherwise, it will be in a deferred state until the `start` API method is called.
|
|
86
86
|
* @property {boolean} [ssl] - If explicitly false, the agent will use HTTP instead of HTTPS. This setting should NOT be used.
|
|
87
|
+
* @property {Object} [browser_consent_mode]
|
|
88
|
+
* @property {boolean} [browser_consent_mode.enabled] - If true, the agent will use consent mode for whether to allow or disallow data harvest.
|
|
87
89
|
* @property {Object} [user_actions]
|
|
88
90
|
* @property {boolean} [user_actions.enabled] - Must be true to allow UserAction events to be captured.
|
|
89
91
|
* @property {Array<string>} [user_actions.elementAttributes] - List of HTML Element properties to be captured with UserAction events' target elements. This may help to identify the source element being interacted with in the UI.
|
|
@@ -53,6 +53,7 @@ const InitModelFn = () => {
|
|
|
53
53
|
set allow_registered_children (val) { hiddenState.experimental.allow_registered_children = val },
|
|
54
54
|
duplicate_registered_data: false
|
|
55
55
|
},
|
|
56
|
+
browser_consent_mode: { enabled: false },
|
|
56
57
|
distributed_tracing: {
|
|
57
58
|
enabled: undefined,
|
|
58
59
|
exclude_newrelic_header: undefined,
|
|
@@ -19,9 +19,19 @@ const ReadOnly = {
|
|
|
19
19
|
originTime
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const hiddenState = {
|
|
23
|
+
consented: false
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
const RuntimeModel = {
|
|
23
27
|
/** Agent-specific metadata found in the RUM call response. ex. entityGuid */
|
|
24
28
|
appMetadata: {},
|
|
29
|
+
get consented () {
|
|
30
|
+
return this.session?.state?.consent || hiddenState.consented
|
|
31
|
+
},
|
|
32
|
+
set consented (value) {
|
|
33
|
+
hiddenState.consented = value
|
|
34
|
+
},
|
|
25
35
|
customTransaction: undefined,
|
|
26
36
|
denyList: undefined,
|
|
27
37
|
disabled: false,
|
|
@@ -18,8 +18,10 @@ import { getSubmitMethod, xhr as xhrMethod, xhrFetch as fetchMethod } from '../u
|
|
|
18
18
|
import { activatedFeatures } from '../util/feature-flags'
|
|
19
19
|
import { dispatchGlobalEvent } from '../dispatch/global-event'
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
const
|
|
21
|
+
const RETRY = 'Harvester/Retry/'
|
|
22
|
+
const RETRY_ATTEMPTED = RETRY + 'Attempted/'
|
|
23
|
+
const RETRY_FAILED = RETRY + 'Failed/'
|
|
24
|
+
const RETRY_SUCCEEDED = RETRY + 'Succeeded/'
|
|
23
25
|
|
|
24
26
|
export class Harvester {
|
|
25
27
|
#started = false
|
|
@@ -57,12 +59,13 @@ export class Harvester {
|
|
|
57
59
|
triggerHarvestFor (aggregateInst, localOpts = {}) {
|
|
58
60
|
const output = { ranSend: false, payload: undefined, endpointVersion: aggregateInst.harvestEndpointVersion || 1 }
|
|
59
61
|
if (aggregateInst.blocked) return output
|
|
62
|
+
if (this.agentRef.init?.browser_consent_mode?.enabled && !this.agentRef.runtime.consented) return output
|
|
60
63
|
|
|
61
64
|
const submitMethod = getSubmitMethod(localOpts)
|
|
62
65
|
if (!submitMethod) return output
|
|
63
66
|
|
|
64
67
|
const shouldRetryOnFail = !localOpts.isFinalHarvest && submitMethod === xhrMethod // always retry all features harvests except for final
|
|
65
|
-
output.payload =
|
|
68
|
+
output.payload = aggregateInst.makeHarvestPayload(shouldRetryOnFail, localOpts)
|
|
66
69
|
|
|
67
70
|
if (!output.payload) return output
|
|
68
71
|
|
|
@@ -86,7 +89,9 @@ export class Harvester {
|
|
|
86
89
|
*/
|
|
87
90
|
function cbFinished (result) {
|
|
88
91
|
if (aggregateInst.harvestOpts.prevAttemptCode) { // this means we just retried a harvest that last failed
|
|
89
|
-
handle(SUPPORTABILITY_METRIC_CHANNEL, [
|
|
92
|
+
const reportSM = (message) => handle(SUPPORTABILITY_METRIC_CHANNEL, [message], undefined, FEATURE_NAMES.metrics, aggregateInst.ee)
|
|
93
|
+
reportSM(RETRY_ATTEMPTED + aggregateInst.featureName)
|
|
94
|
+
reportSM((result.retry ? RETRY_FAILED : RETRY_SUCCEEDED) + aggregateInst.harvestOpts.prevAttemptCode)
|
|
90
95
|
delete aggregateInst.harvestOpts.prevAttemptCode // always reset last observation so we don't falsely report again next harvest
|
|
91
96
|
// In case this re-attempt failed again, that'll be handled (re-marked again) next.
|
|
92
97
|
}
|
|
@@ -155,8 +160,7 @@ export function send (agentRef, { endpoint, payload, localOpts = {}, submitMetho
|
|
|
155
160
|
result.addEventListener('loadend', function () {
|
|
156
161
|
// `this` here in block refers to the XHR object in this scope, do not change the anon function to an arrow function
|
|
157
162
|
// status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
|
|
158
|
-
const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), fullUrl, xhr: this }
|
|
159
|
-
if (localOpts.needResponse) cbResult.responseText = this.responseText
|
|
163
|
+
const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), fullUrl, xhr: this, responseText: this.responseText }
|
|
160
164
|
cbFinished(cbResult)
|
|
161
165
|
|
|
162
166
|
/** temporary audit of consistency of harvest metadata flags */
|
|
@@ -165,8 +169,7 @@ export function send (agentRef, { endpoint, payload, localOpts = {}, submitMetho
|
|
|
165
169
|
} else if (submitMethod === fetchMethod) {
|
|
166
170
|
result.then(async function (response) {
|
|
167
171
|
const status = response.status
|
|
168
|
-
const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response }
|
|
169
|
-
if (localOpts.needResponse) cbResult.responseText = await response.text()
|
|
172
|
+
const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response, responseText: await response.text() }
|
|
170
173
|
cbFinished(cbResult)
|
|
171
174
|
/** temporary audit of consistency of harvest metadata flags */
|
|
172
175
|
if (!shouldRetry(status)) trackHarvestMetadata()
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
* @property {HarvestEndpointIdentifier} endpoint The endpoint to use (jserrors, events, resources etc.)
|
|
25
25
|
* @property {HarvestPayload} payload Object representing payload.
|
|
26
26
|
* @property {object} localOpts Additional options for sending data
|
|
27
|
-
* @property {boolean} localOpts.needResponse Specify whether the caller expects a response data.
|
|
28
27
|
* @property {boolean} localOpts.isFinalHarvest Specify whether the call is a final harvest during page unload.
|
|
29
28
|
* @property {boolean} localOpts.sendEmptyBody Specify whether the call should be made even if the body is empty. Useful for rum calls.
|
|
30
29
|
* @property {boolean} localOpts.forceNoRetry Don't save the buffered data in the case of a need to retry the transmission.
|
|
@@ -32,7 +32,8 @@ const model = {
|
|
|
32
32
|
loggingMode: LOGGING_MODE.OFF,
|
|
33
33
|
serverTimeDiff: null, // set by TimeKeeper; "undefined" value will not be stringified and stored but "null" will
|
|
34
34
|
custom: {},
|
|
35
|
-
numOfResets: 0
|
|
35
|
+
numOfResets: 0,
|
|
36
|
+
consent: false // set by consent() API call
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
export class SessionEntity {
|
|
@@ -77,7 +78,10 @@ export class SessionEntity {
|
|
|
77
78
|
|
|
78
79
|
setup ({ value = generateRandomHexString(16), expiresMs = DEFAULT_EXPIRES_MS, inactiveMs = DEFAULT_INACTIVE_MS, numOfResets = 0 }) {
|
|
79
80
|
/** Ensure that certain properties are preserved across a reset if already set */
|
|
80
|
-
const persistentAttributes = {
|
|
81
|
+
const persistentAttributes = {
|
|
82
|
+
serverTimeDiff: this.state.serverTimeDiff || model.serverTimeDiff,
|
|
83
|
+
consent: this.state.consent || model.consent
|
|
84
|
+
}
|
|
81
85
|
this.state = {}
|
|
82
86
|
this.sync({ ...model, ...persistentAttributes })
|
|
83
87
|
|
package/src/common/util/mfe.js
CHANGED
|
@@ -11,8 +11,14 @@ export function isValidMFETarget (target = {}) {
|
|
|
11
11
|
return !!(target.id && target.name)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export function hasValidValue (val) {
|
|
15
|
+
return (typeof val === 'string' && val.trim().length < 501) || (typeof val === 'number')
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
/**
|
|
15
19
|
* When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
|
|
20
|
+
* @note Field names may change as the schema is finalized
|
|
21
|
+
*
|
|
16
22
|
* @param {Object} [target] the registered target
|
|
17
23
|
* @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
|
|
18
24
|
* @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
|
|
@@ -27,9 +33,9 @@ export function getVersion2Attributes (target, aggregateInstance) {
|
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
35
|
return {
|
|
30
|
-
'mfe.id': target.id,
|
|
31
|
-
'mfe.name': target.name,
|
|
32
|
-
eventSource:
|
|
33
|
-
'parent.id': containerAgentEntityGuid
|
|
36
|
+
'mfe.id': target.id,
|
|
37
|
+
'mfe.name': target.name,
|
|
38
|
+
eventSource: target.eventSource,
|
|
39
|
+
'parent.id': target.parent?.id || containerAgentEntityGuid
|
|
34
40
|
}
|
|
35
41
|
}
|
|
@@ -140,13 +140,23 @@ export function wrapPromise (sharedEE) {
|
|
|
140
140
|
|
|
141
141
|
promiseEE.on('propagate', function (val, overwrite, trigger) {
|
|
142
142
|
if (!this.getCtx || overwrite) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
const selfStore = this
|
|
144
|
+
const parentStore =
|
|
145
|
+
val instanceof Promise ? promiseEE.context(val) : null
|
|
146
|
+
let cachedCtx
|
|
147
|
+
|
|
148
|
+
this.getCtx = function getCtx () {
|
|
149
|
+
if (cachedCtx) return cachedCtx
|
|
150
|
+
|
|
151
|
+
if (parentStore && parentStore !== selfStore) {
|
|
152
|
+
cachedCtx =
|
|
153
|
+
typeof parentStore.getCtx === 'function'
|
|
154
|
+
? parentStore.getCtx()
|
|
155
|
+
: parentStore
|
|
156
|
+
} else {
|
|
157
|
+
cachedCtx = selfStore
|
|
147
158
|
}
|
|
148
|
-
|
|
149
|
-
return store && store.getCtx ? store.getCtx() : this
|
|
159
|
+
return cachedCtx
|
|
150
160
|
}
|
|
151
161
|
}
|
|
152
162
|
})
|
|
@@ -33,13 +33,13 @@ export class Aggregate extends AggregateBase {
|
|
|
33
33
|
|
|
34
34
|
this.#trackSupportabilityMetrics()
|
|
35
35
|
|
|
36
|
-
registerHandler('api-recordCustomEvent', (timestamp, eventType, attributes) => {
|
|
36
|
+
registerHandler('api-recordCustomEvent', (timestamp, eventType, attributes, target) => {
|
|
37
37
|
if (RESERVED_EVENT_TYPES.includes(eventType)) return warn(46)
|
|
38
38
|
this.addEvent({
|
|
39
39
|
eventType,
|
|
40
40
|
timestamp: this.toEpoch(timestamp),
|
|
41
41
|
...attributes
|
|
42
|
-
})
|
|
42
|
+
}, target)
|
|
43
43
|
}, this.featureName, this.ee)
|
|
44
44
|
|
|
45
45
|
if (agentRef.init.page_action.enabled) {
|
|
@@ -227,7 +227,7 @@ export class Aggregate extends AggregateBase {
|
|
|
227
227
|
}, this.featureName, this.ee)
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
registerHandler('api-measure', (args, n) => {
|
|
230
|
+
registerHandler('api-measure', (args, n, target) => {
|
|
231
231
|
const { start, duration, customAttributes } = args
|
|
232
232
|
|
|
233
233
|
const event = {
|
|
@@ -239,7 +239,7 @@ export class Aggregate extends AggregateBase {
|
|
|
239
239
|
entryType: 'measure'
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
this.addEvent(event)
|
|
242
|
+
this.addEvent(event, target)
|
|
243
243
|
}, this.featureName, this.ee)
|
|
244
244
|
|
|
245
245
|
this.drain()
|
|
@@ -116,7 +116,7 @@ export class Aggregate extends AggregateBase {
|
|
|
116
116
|
common: {
|
|
117
117
|
/** Attributes in the `common` section are added to `all` logs generated in the payload */
|
|
118
118
|
attributes: {
|
|
119
|
-
...this.agentRef.info.jsAttributes,
|
|
119
|
+
...(applyFnToProps(this.agentRef.info.jsAttributes, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')),
|
|
120
120
|
...(this.harvestEndpointVersion === 1 && {
|
|
121
121
|
'entity.guid': this.agentRef.runtime.appMetadata.agents[0].entityGuid,
|
|
122
122
|
appId: this.agentRef.info.applicationID
|
|
@@ -17,15 +17,22 @@ import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte'
|
|
|
17
17
|
import { now } from '../../../common/timing/now'
|
|
18
18
|
import { TimeKeeper } from '../../../common/timing/time-keeper'
|
|
19
19
|
import { applyFnToProps } from '../../../common/util/traverse'
|
|
20
|
+
import { send } from '../../../common/harvest/harvester'
|
|
21
|
+
import { FEATURE_NAMES, FEATURE_TO_ENDPOINT } from '../../../loaders/features/features'
|
|
22
|
+
import { getSubmitMethod } from '../../../common/util/submit-data'
|
|
20
23
|
|
|
21
24
|
export class Aggregate extends AggregateBase {
|
|
22
25
|
static featureName = CONSTANTS.FEATURE_NAME
|
|
26
|
+
|
|
23
27
|
constructor (agentRef) {
|
|
24
28
|
super(agentRef, CONSTANTS.FEATURE_NAME)
|
|
25
29
|
|
|
30
|
+
this.sentRum = false // flag to facilitate calling sendRum() once externally (by the consent API in agent-session.js)
|
|
31
|
+
|
|
26
32
|
this.timeToFirstByte = 0
|
|
27
33
|
this.firstByteToWindowLoad = 0 // our "frontend" duration
|
|
28
34
|
this.firstByteToDomContent = 0 // our "dom processing" duration
|
|
35
|
+
this.retries = 0
|
|
29
36
|
|
|
30
37
|
if (!isValid(agentRef.info)) {
|
|
31
38
|
this.ee.abort()
|
|
@@ -52,9 +59,8 @@ export class Aggregate extends AggregateBase {
|
|
|
52
59
|
*
|
|
53
60
|
* @param {Function} cb A function to run once the RUM call has finished - Defaults to activateFeatures
|
|
54
61
|
* @param {*} customAttributes custom attributes to attach to the RUM call - Defaults to info.js
|
|
55
|
-
* @param {*} target The target to harvest to
|
|
56
62
|
*/
|
|
57
|
-
sendRum (customAttributes = this.agentRef.info.jsAttributes
|
|
63
|
+
sendRum (customAttributes = this.agentRef.info.jsAttributes) {
|
|
58
64
|
const info = this.agentRef.info
|
|
59
65
|
const measures = {}
|
|
60
66
|
|
|
@@ -107,24 +113,26 @@ export class Aggregate extends AggregateBase {
|
|
|
107
113
|
queryParameters.fp = firstPaint.current.value
|
|
108
114
|
queryParameters.fcp = firstContentfulPaint.current.value
|
|
109
115
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
this.queryStringsBuilder = () => { // this will be called by AggregateBase.makeHarvestPayload every time harvest is triggered to be qs
|
|
117
|
+
this.rumStartTime = now() // this should be reset at the beginning of each RUM call for proper timeKeeper calculation in coordination with postHarvestCleanup
|
|
118
|
+
const timeKeeper = this.agentRef.runtime.timeKeeper
|
|
119
|
+
if (timeKeeper?.ready) {
|
|
120
|
+
queryParameters.timestamp = Math.floor(timeKeeper.correctRelativeTimestamp(this.rumStartTime))
|
|
121
|
+
}
|
|
122
|
+
return queryParameters
|
|
113
123
|
}
|
|
124
|
+
this.events.add(body)
|
|
114
125
|
|
|
115
|
-
this.
|
|
116
|
-
|
|
117
|
-
this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
118
|
-
directSend: {
|
|
119
|
-
target,
|
|
120
|
-
payload: { qs: queryParameters, body }
|
|
121
|
-
},
|
|
122
|
-
needResponse: true,
|
|
126
|
+
if (this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
123
127
|
sendEmptyBody: true
|
|
124
|
-
})
|
|
128
|
+
}).ranSend) this.sentRum = true
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
serializer (eventBuffer) { // this is necessary because PVE sends a single item rather than an array; in the case of undefined, this prevents sending [null] as body
|
|
132
|
+
return eventBuffer[0]
|
|
125
133
|
}
|
|
126
134
|
|
|
127
|
-
postHarvestCleanup ({ status, responseText, xhr }) {
|
|
135
|
+
postHarvestCleanup ({ sent, status, responseText, xhr, retry }) {
|
|
128
136
|
const rumEndTime = now()
|
|
129
137
|
let app, flags
|
|
130
138
|
try {
|
|
@@ -134,8 +142,63 @@ export class Aggregate extends AggregateBase {
|
|
|
134
142
|
warn(53, error)
|
|
135
143
|
}
|
|
136
144
|
|
|
145
|
+
super.postHarvestCleanup({ sent, retry }) // this will set isRetrying & re-buffer the body if request is to be retried
|
|
146
|
+
if (this.isRetrying && this.retries++ < 1) { // Only retry once
|
|
147
|
+
setTimeout(() => this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
148
|
+
sendEmptyBody: true
|
|
149
|
+
}), 5000) // Retry sending the RUM event after 5 seconds
|
|
150
|
+
return
|
|
151
|
+
}
|
|
137
152
|
if (status >= 400 || status === 0) {
|
|
138
153
|
warn(18, status)
|
|
154
|
+
this.blocked = true
|
|
155
|
+
|
|
156
|
+
// Get estimated payload size of our backlog
|
|
157
|
+
const textEncoder = new TextEncoder()
|
|
158
|
+
const payloadSize = Object.values(newrelic.ee.backlog).reduce((acc, value) => {
|
|
159
|
+
if (!value) return acc
|
|
160
|
+
|
|
161
|
+
const encoded = textEncoder.encode(value)
|
|
162
|
+
return acc + encoded.byteLength
|
|
163
|
+
}, 0)
|
|
164
|
+
|
|
165
|
+
// Send SMs about failed RUM request
|
|
166
|
+
const body = {
|
|
167
|
+
sm: [{
|
|
168
|
+
params: {
|
|
169
|
+
name: `Browser/Supportability/BCS/Error/${status}`
|
|
170
|
+
},
|
|
171
|
+
stats: {
|
|
172
|
+
c: 1
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
params: {
|
|
177
|
+
name: 'Browser/Supportability/BCS/Error/Dropped/Bytes'
|
|
178
|
+
},
|
|
179
|
+
stats: {
|
|
180
|
+
c: 1,
|
|
181
|
+
t: payloadSize
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
params: {
|
|
186
|
+
name: 'Browser/Supportability/BCS/Error/Duration/Ms'
|
|
187
|
+
},
|
|
188
|
+
stats: {
|
|
189
|
+
c: 1,
|
|
190
|
+
t: rumEndTime - this.rumStartTime
|
|
191
|
+
}
|
|
192
|
+
}]
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
send(this.agentRef, {
|
|
196
|
+
endpoint: FEATURE_TO_ENDPOINT[FEATURE_NAMES.metrics],
|
|
197
|
+
payload: { body },
|
|
198
|
+
submitMethod: getSubmitMethod(),
|
|
199
|
+
featureName: FEATURE_NAMES.metrics
|
|
200
|
+
})
|
|
201
|
+
|
|
139
202
|
// Adding retry logic for the rum call will be a separate change; this.blocked will need to be changed since that prevents another triggerHarvestFor()
|
|
140
203
|
this.ee.abort()
|
|
141
204
|
return
|
|
@@ -155,6 +218,7 @@ export class Aggregate extends AggregateBase {
|
|
|
155
218
|
}
|
|
156
219
|
} catch (error) {
|
|
157
220
|
this.ee.abort()
|
|
221
|
+
this.blocked = true
|
|
158
222
|
warn(17, error)
|
|
159
223
|
return
|
|
160
224
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { handle } from '../../../common/event-emitter/handle'
|
|
6
5
|
import { setupSetPageViewNameAPI } from '../../../loaders/api/setPageViewName'
|
|
7
6
|
import { InstrumentBase } from '../../utils/instrument-base'
|
|
8
7
|
import * as CONSTANTS from '../constants'
|
|
@@ -21,9 +20,6 @@ export class Instrument extends InstrumentBase {
|
|
|
21
20
|
/** feature specific APIs */
|
|
22
21
|
setupSetPageViewNameAPI(agentRef)
|
|
23
22
|
|
|
24
|
-
/** messages from the register API that can trigger a new RUM call */
|
|
25
|
-
this.ee.on('api-send-rum', (attrs, target) => handle('send-rum', [attrs, target], undefined, this.featureName, this.ee))
|
|
26
|
-
|
|
27
23
|
this.importAggregator(agentRef, () => import(/* webpackChunkName: "page_view_event-aggregate" */ '../aggregate'))
|
|
28
24
|
}
|
|
29
25
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
10
|
-
import { ABORT_REASONS, FEATURE_NAME, QUERY_PARAM_PADDING, RRWEB_EVENT_TYPES,
|
|
10
|
+
import { ABORT_REASONS, ERROR_DURING_REPLAY, FEATURE_NAME, QUERY_PARAM_PADDING, RRWEB_EVENT_TYPES, TRIGGERS } from '../constants'
|
|
11
11
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
12
12
|
import { sharedChannel } from '../../../common/constants/shared-channel'
|
|
13
13
|
import { obj as encodeObj } from '../../../common/url/encode'
|
|
@@ -21,6 +21,7 @@ import { now } from '../../../common/timing/now'
|
|
|
21
21
|
import { MAX_PAYLOAD_SIZE } from '../../../common/constants/agent-constants'
|
|
22
22
|
import { cleanURL } from '../../../common/url/clean-url'
|
|
23
23
|
import { canEnableSessionTracking } from '../../utils/feature-gates'
|
|
24
|
+
import { PAUSE_REPLAY } from '../../../loaders/api/constants'
|
|
24
25
|
|
|
25
26
|
export class Aggregate extends AggregateBase {
|
|
26
27
|
static featureName = FEATURE_NAME
|
|
@@ -77,11 +78,11 @@ export class Aggregate extends AggregateBase {
|
|
|
77
78
|
this.mode = data.sessionReplayMode
|
|
78
79
|
})
|
|
79
80
|
|
|
80
|
-
registerHandler(
|
|
81
|
+
registerHandler(PAUSE_REPLAY, () => {
|
|
81
82
|
this.forceStop(this.mode === MODE.FULL)
|
|
82
83
|
}, this.featureName, this.ee)
|
|
83
84
|
|
|
84
|
-
registerHandler(
|
|
85
|
+
registerHandler(ERROR_DURING_REPLAY, e => {
|
|
85
86
|
this.handleError(e)
|
|
86
87
|
}, this.featureName, this.ee)
|
|
87
88
|
|
|
@@ -7,11 +7,7 @@ import { FEATURE_NAMES } from '../../loaders/features/features'
|
|
|
7
7
|
|
|
8
8
|
export const FEATURE_NAME = FEATURE_NAMES.sessionReplay
|
|
9
9
|
|
|
10
|
-
export const
|
|
11
|
-
RECORD: 'recordReplay',
|
|
12
|
-
PAUSE: 'pauseReplay',
|
|
13
|
-
ERROR_DURING_REPLAY: 'errorDuringReplay'
|
|
14
|
-
}
|
|
10
|
+
export const ERROR_DURING_REPLAY = 'errorDuringReplay'
|
|
15
11
|
|
|
16
12
|
export const AVG_COMPRESSION = 0.12
|
|
17
13
|
export const RRWEB_EVENT_TYPES = {
|
|
@@ -10,9 +10,10 @@ import { handle } from '../../../common/event-emitter/handle'
|
|
|
10
10
|
import { DEFAULT_KEY, MODE, PREFIX } from '../../../common/session/constants'
|
|
11
11
|
import { InstrumentBase } from '../../utils/instrument-base'
|
|
12
12
|
import { hasReplayPrerequisite, isPreloadAllowed } from '../shared/utils'
|
|
13
|
-
import {
|
|
13
|
+
import { ERROR_DURING_REPLAY, FEATURE_NAME, TRIGGERS } from '../constants'
|
|
14
14
|
import { setupRecordReplayAPI } from '../../../loaders/api/recordReplay'
|
|
15
15
|
import { setupPauseReplayAPI } from '../../../loaders/api/pauseReplay'
|
|
16
|
+
import { RECORD_REPLAY } from '../../../loaders/api/constants'
|
|
16
17
|
|
|
17
18
|
export class Instrument extends InstrumentBase {
|
|
18
19
|
static featureName = FEATURE_NAME
|
|
@@ -34,7 +35,7 @@ export class Instrument extends InstrumentBase {
|
|
|
34
35
|
} catch (err) { }
|
|
35
36
|
|
|
36
37
|
if (hasReplayPrerequisite(agentRef.init)) {
|
|
37
|
-
this.ee.on(
|
|
38
|
+
this.ee.on(RECORD_REPLAY, () => this.#apiStartOrRestartReplay())
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
if (this.#canPreloadRecorder(session)) {
|
|
@@ -50,7 +51,7 @@ export class Instrument extends InstrumentBase {
|
|
|
50
51
|
if (this.blocked) return
|
|
51
52
|
if (this.agentRef.runtime.isRecording) {
|
|
52
53
|
this.errorNoticed = true
|
|
53
|
-
handle(
|
|
54
|
+
handle(ERROR_DURING_REPLAY, [e], undefined, this.featureName, this.ee)
|
|
54
55
|
}
|
|
55
56
|
})
|
|
56
57
|
}
|
|
@@ -56,6 +56,10 @@ export function setupAgentSession (agentRef) {
|
|
|
56
56
|
agentRef.runtime.session.syncCustomAttribute(key, value)
|
|
57
57
|
}, 'session', sharedEE)
|
|
58
58
|
|
|
59
|
+
registerHandler('api-consent', (accept) => {
|
|
60
|
+
agentRef.runtime.session.write({ consent: accept === undefined ? true : accept })
|
|
61
|
+
}, 'session', sharedEE)
|
|
62
|
+
|
|
59
63
|
drain(agentRef.agentIdentifier, 'session')
|
|
60
64
|
|
|
61
65
|
return agentRef.runtime.session
|
|
@@ -49,7 +49,10 @@ export class InstrumentBase extends FeatureBase {
|
|
|
49
49
|
* @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
|
|
50
50
|
* one another if there are inter-features dependencies.
|
|
51
51
|
*/
|
|
52
|
-
this.
|
|
52
|
+
this.loadedSuccessfully = undefined
|
|
53
|
+
this.onAggregateImported = new Promise(resolve => {
|
|
54
|
+
this.loadedSuccessfully = resolve
|
|
55
|
+
})
|
|
53
56
|
|
|
54
57
|
/**
|
|
55
58
|
* used in conjunction with newrelic.start() to defer harvesting in features
|
|
@@ -83,11 +86,6 @@ export class InstrumentBase extends FeatureBase {
|
|
|
83
86
|
importAggregator (agentRef, fetchAggregator, argsObjFromInstrument = {}) {
|
|
84
87
|
if (this.featAggregate) return
|
|
85
88
|
|
|
86
|
-
let loadedSuccessfully
|
|
87
|
-
this.onAggregateImported = new Promise(resolve => {
|
|
88
|
-
loadedSuccessfully = resolve
|
|
89
|
-
})
|
|
90
|
-
|
|
91
89
|
const importLater = async () => {
|
|
92
90
|
// wait for the deferred promise to resolve before proceeding
|
|
93
91
|
// this will resolve immediately if the feature is auto-started,
|
|
@@ -113,20 +111,20 @@ export class InstrumentBase extends FeatureBase {
|
|
|
113
111
|
try {
|
|
114
112
|
if (!this.#shouldImportAgg(this.featureName, session, agentRef.init)) {
|
|
115
113
|
drain(this.agentIdentifier, this.featureName)
|
|
116
|
-
loadedSuccessfully(false) // aggregate module isn't loaded at all
|
|
114
|
+
this.loadedSuccessfully(false) // aggregate module isn't loaded at all
|
|
117
115
|
return
|
|
118
116
|
}
|
|
119
117
|
const { Aggregate } = await fetchAggregator()
|
|
120
118
|
this.featAggregate = new Aggregate(agentRef, argsObjFromInstrument)
|
|
121
119
|
|
|
122
120
|
agentRef.runtime.harvester.initializedAggregates.push(this.featAggregate) // "subscribe" the feature to future harvest intervals (PVE will start the timer)
|
|
123
|
-
loadedSuccessfully(true)
|
|
121
|
+
this.loadedSuccessfully(true)
|
|
124
122
|
} catch (e) {
|
|
125
123
|
warn(34, e)
|
|
126
124
|
this.abortHandler?.() // undo any important alterations made to the page
|
|
127
125
|
// not supported yet but nice to do: "abort" this agent's EE for this feature specifically
|
|
128
126
|
drain(this.agentIdentifier, this.featureName, true)
|
|
129
|
-
loadedSuccessfully(false)
|
|
127
|
+
this.loadedSuccessfully(false)
|
|
130
128
|
if (this.ee) this.ee.abort()
|
|
131
129
|
}
|
|
132
130
|
}
|
|
@@ -48,6 +48,27 @@ export class RegisteredEntity {
|
|
|
48
48
|
warn(35, 'addPageAction')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Records a custom event with a specified eventType and attributes.
|
|
53
|
+
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/recordCustomEvent/}
|
|
54
|
+
* @param {string} eventType The eventType to store the event as.
|
|
55
|
+
* @param {Object} [attributes] JSON object with one or more key/value pairs. For example: {key:"value"}.
|
|
56
|
+
*/
|
|
57
|
+
recordCustomEvent (eventType, attributes) {
|
|
58
|
+
warn(35, 'recordCustomEvent')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Measures a task that is recorded as a BrowserPerformance event.
|
|
63
|
+
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/measure/}
|
|
64
|
+
* @param {string} name The name of the task
|
|
65
|
+
* @param {{start: number, end: number, duration: number, customAttributes: object}} [options] An object used to control the way the measure API operates
|
|
66
|
+
* @returns {{start: number, end: number, duration: number, customAttributes: object}} Measurement details
|
|
67
|
+
*/
|
|
68
|
+
measure (name, options) {
|
|
69
|
+
warn(35, 'measure')
|
|
70
|
+
}
|
|
71
|
+
|
|
51
72
|
/**
|
|
52
73
|
* Adds a user-defined attribute name and value to subsequent events on the page for the registered target. Note -- the persist flag does not work with the register API.
|
|
53
74
|
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setcustomattribute/}
|
package/src/loaders/agent.js
CHANGED
|
@@ -23,6 +23,7 @@ import { setupSetCustomAttributeAPI } from './api/setCustomAttribute'
|
|
|
23
23
|
import { setupSetUserIdAPI } from './api/setUserId'
|
|
24
24
|
import { setupSetApplicationVersionAPI } from './api/setApplicationVersion'
|
|
25
25
|
import { setupStartAPI } from './api/start'
|
|
26
|
+
import { setupConsentAPI } from './api/consent'
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* @typedef {Object} AgentOptions
|
|
@@ -70,6 +71,7 @@ export class Agent extends AgentBase {
|
|
|
70
71
|
setupSetUserIdAPI(this)
|
|
71
72
|
setupSetApplicationVersionAPI(this)
|
|
72
73
|
setupStartAPI(this)
|
|
74
|
+
setupConsentAPI(this)
|
|
73
75
|
|
|
74
76
|
this.run()
|
|
75
77
|
}
|