@newrelic/browser-agent 1.312.1 → 1.313.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 +16 -0
- package/dist/cjs/common/config/init-types.js +3 -2
- package/dist/cjs/common/config/init.js +10 -8
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/timing/time-keeper.js +28 -1
- package/dist/cjs/common/util/short-circuit.js +13 -0
- package/dist/cjs/common/util/submit-data.js +2 -9
- package/dist/cjs/common/v2/script-correlation.js +50 -0
- package/dist/cjs/common/v2/script-tracker.js +278 -0
- package/dist/cjs/common/{util/v2.js → v2/utils.js} +4 -4
- package/dist/cjs/common/wrap/wrap-fetch.js +2 -2
- package/dist/cjs/common/wrap/wrap-function.js +2 -2
- package/dist/cjs/common/wrap/wrap-xhr.js +2 -2
- package/dist/cjs/features/ajax/aggregate/index.js +4 -4
- package/dist/cjs/features/generic_events/aggregate/index.js +21 -2
- package/dist/cjs/features/generic_events/instrument/index.js +24 -21
- package/dist/cjs/features/jserrors/aggregate/index.js +206 -40
- package/dist/cjs/features/logging/aggregate/index.js +4 -4
- package/dist/cjs/features/metrics/instrument/index.js +1 -8
- package/dist/cjs/features/session_trace/aggregate/index.js +3 -4
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +2 -2
- package/dist/cjs/interfaces/registered-entity.js +7 -20
- package/dist/cjs/loaders/api/register-api-types.js +8 -8
- package/dist/cjs/loaders/api/register.js +49 -43
- package/dist/esm/common/config/init-types.js +3 -2
- package/dist/esm/common/config/init.js +10 -8
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/timing/time-keeper.js +28 -1
- package/dist/esm/common/util/short-circuit.js +6 -0
- package/dist/esm/common/util/submit-data.js +2 -9
- package/dist/esm/common/v2/script-correlation.js +43 -0
- package/dist/esm/common/v2/script-tracker.js +270 -0
- package/dist/esm/common/{util/v2.js → v2/utils.js} +4 -4
- package/dist/esm/common/wrap/wrap-fetch.js +1 -1
- package/dist/esm/common/wrap/wrap-function.js +1 -1
- package/dist/esm/common/wrap/wrap-xhr.js +1 -1
- package/dist/esm/features/ajax/aggregate/index.js +1 -1
- package/dist/esm/features/generic_events/aggregate/index.js +20 -1
- package/dist/esm/features/generic_events/instrument/index.js +24 -21
- package/dist/esm/features/jserrors/aggregate/index.js +205 -39
- package/dist/esm/features/logging/aggregate/index.js +1 -1
- package/dist/esm/features/metrics/instrument/index.js +2 -9
- package/dist/esm/features/session_trace/aggregate/index.js +4 -5
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +2 -2
- package/dist/esm/interfaces/registered-entity.js +7 -20
- package/dist/esm/loaders/api/register-api-types.js +8 -8
- package/dist/esm/loaders/api/register.js +46 -41
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +10 -8
- 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/timing/time-keeper.d.ts.map +1 -1
- package/dist/types/common/util/short-circuit.d.ts +8 -0
- package/dist/types/common/util/short-circuit.d.ts.map +1 -0
- package/dist/types/common/util/submit-data.d.ts.map +1 -1
- package/dist/types/common/v2/script-correlation.d.ts +38 -0
- package/dist/types/common/v2/script-correlation.d.ts.map +1 -0
- package/dist/types/common/{util → v2}/script-tracker.d.ts +3 -0
- package/dist/types/common/v2/script-tracker.d.ts.map +1 -0
- package/dist/types/common/{util/v2.d.ts → v2/utils.d.ts} +1 -1
- package/dist/types/common/v2/utils.d.ts.map +1 -0
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +25 -16
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/interfaces/registered-entity.d.ts +0 -10
- package/dist/types/interfaces/registered-entity.d.ts.map +1 -1
- package/dist/types/loaders/api/register-api-types.d.ts +15 -15
- package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
- package/dist/types/loaders/api/register.d.ts +6 -0
- package/dist/types/loaders/api/register.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/config/init-types.js +3 -2
- package/src/common/config/init.js +6 -4
- package/src/common/timing/time-keeper.js +30 -1
- package/src/common/util/short-circuit.js +6 -0
- package/src/common/util/submit-data.js +2 -8
- package/src/common/v2/script-correlation.js +44 -0
- package/src/common/v2/script-tracker.js +260 -0
- package/src/common/{util/v2.js → v2/utils.js} +4 -4
- package/src/common/wrap/wrap-fetch.js +1 -1
- package/src/common/wrap/wrap-function.js +1 -1
- package/src/common/wrap/wrap-xhr.js +1 -1
- package/src/features/ajax/aggregate/index.js +1 -1
- package/src/features/generic_events/aggregate/index.js +20 -1
- package/src/features/generic_events/instrument/index.js +25 -22
- package/src/features/jserrors/aggregate/index.js +200 -43
- package/src/features/logging/aggregate/index.js +1 -1
- package/src/features/metrics/instrument/index.js +2 -13
- package/src/features/session_trace/aggregate/index.js +4 -6
- package/src/features/session_trace/aggregate/trace/storage.js +2 -2
- package/src/interfaces/registered-entity.js +8 -20
- package/src/loaders/api/register-api-types.js +8 -8
- package/src/loaders/api/register.js +42 -34
- package/dist/cjs/common/util/script-tracker.js +0 -204
- package/dist/esm/common/util/script-tracker.js +0 -196
- package/dist/types/common/util/script-tracker.d.ts.map +0 -1
- package/dist/types/common/util/v2.d.ts.map +0 -1
- package/src/common/util/script-tracker.js +0 -189
|
@@ -13,7 +13,6 @@ exports.default = void 0;
|
|
|
13
13
|
* @property {(name: string, attributes?: object) => void} addPageAction - Add a page action for the registered entity.
|
|
14
14
|
* @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
|
|
15
15
|
* @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
|
|
16
|
-
* @property {(target: RegisterAPIConstructor) => RegisterAPI} register - Record a custom event for the registered entity.
|
|
17
16
|
* @property {() => void} deregister - Deregister the registered entity, which blocks its use and captures end of life timings.
|
|
18
17
|
* @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
|
|
19
18
|
* @property {(eventType: string, options?: {start?: number|PerformanceMark, end?: number|PerformanceMark, customAttributes?: object}) => ({start: number, end: number, duration: number, customAttributes: object})} measure - Measures a task that is recorded as a BrowserPerformance event.
|
|
@@ -27,14 +26,14 @@ exports.default = void 0;
|
|
|
27
26
|
* @property {string} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
|
|
28
27
|
* @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
|
|
29
28
|
* @property {{[key: string]: any}} [tags] - The tags for the registered entity as key-value pairs. This will be assigned to any synthesized entities. Tags are converted to source.* attributes (e.g., {environment: 'production'} becomes source.environment: 'production').
|
|
30
|
-
* @property {
|
|
29
|
+
* @property {RegisterAPITarget} [parent] - The parent target for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
|
|
31
30
|
* @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
|
|
32
31
|
*/
|
|
33
32
|
/**
|
|
34
33
|
* @typedef {Object} RegisterAPIMetadata
|
|
35
34
|
* @property {Object} customAttributes - The custom attributes for the registered entity.
|
|
36
|
-
* @property {RegisterAPITimings} timings - The timing metrics for the registered entity.
|
|
37
|
-
* @property {RegisterAPITarget} target - The options for the registered entity.
|
|
35
|
+
* @property {Partial<RegisterAPITimings>} timings - The timing metrics for the registered entity.
|
|
36
|
+
* @property {Partial<RegisterAPITarget>} target - The options for the registered entity.
|
|
38
37
|
*/
|
|
39
38
|
/**
|
|
40
39
|
* @typedef {Object} RegisterAPITarget
|
|
@@ -42,15 +41,16 @@ exports.default = void 0;
|
|
|
42
41
|
* @property {string} name - The name returned for the registered entity.
|
|
43
42
|
* @property {{[key: string]: any}} [tags] - The tags for the registered entity as key-value pairs.
|
|
44
43
|
* @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
|
|
45
|
-
* @property {boolean} [isolated] - When true, each registration creates an isolated instance. When false, multiple registrations with the same id and isolated: false will share a single instance, including all custom attributes, ids, names, and metadata. Calling deregister on a shared instance will deregister it for all entities using the instance. Defaults to true.
|
|
46
44
|
*/
|
|
47
45
|
/**
|
|
48
46
|
* @typedef {Object} RegisterAPITimings
|
|
49
47
|
* @property {number} registeredAt - The timestamp when the registered entity was created.
|
|
50
48
|
* @property {number} [reportedAt] - The timestamp when the registered entity was deregistered.
|
|
51
|
-
* @property {number} fetchStart - The timestamp when the registered entity began fetching.
|
|
52
|
-
* @property {number} fetchEnd - The timestamp when the registered entity finished fetching.
|
|
49
|
+
* @property {number} fetchStart - The timestamp when the registered entity began fetching (performance.start).
|
|
50
|
+
* @property {number} fetchEnd - The timestamp when the registered entity finished fetching (performance.end).
|
|
51
|
+
* @property {number} scriptStart - The timestamp when script initialization began (max of dom.start or performance.end, or performance.end if no dom.start).
|
|
52
|
+
* @property {number} scriptEnd - The timestamp when script loading completed (dom.end or registeredAt if no dom.end).
|
|
53
53
|
* @property {Object} [asset] - The asset path (if found) for the registered entity.
|
|
54
|
-
* @property {string} type - The type of timing associated with the registered entity, 'script' or 'link' if found with the performance resource API, 'inline' if found to be associated with the root document URL, or 'unknown' if no associated resource could be found.
|
|
54
|
+
* @property {string} type - The type of timing associated with the registered entity, 'script' or 'link' if found with the performance resource API, 'fetch' for dynamic imports, 'inline' if found to be associated with the root document URL, or 'unknown' if no associated resource could be found.
|
|
55
55
|
*/
|
|
56
56
|
var _default = exports.default = {};
|
|
@@ -4,9 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.setupRegisterAPI = setupRegisterAPI;
|
|
7
|
+
exports.warnings = void 0;
|
|
7
8
|
var _handle = require("../../common/event-emitter/handle");
|
|
8
9
|
var _console = require("../../common/util/console");
|
|
9
|
-
var
|
|
10
|
+
var _utils = require("../../common/v2/utils");
|
|
10
11
|
var _features = require("../features/features");
|
|
11
12
|
var _now = require("../../common/timing/now");
|
|
12
13
|
var _constants = require("../../features/metrics/constants");
|
|
@@ -19,7 +20,7 @@ var _invoke = require("../../common/util/invoke");
|
|
|
19
20
|
var _measure = require("./measure");
|
|
20
21
|
var _recordCustomEvent = require("./recordCustomEvent");
|
|
21
22
|
var _pageVisibility = require("../../common/window/page-visibility");
|
|
22
|
-
var _scriptTracker = require("../../common/
|
|
23
|
+
var _scriptTracker = require("../../common/v2/script-tracker");
|
|
23
24
|
var _uniqueId = require("../../common/ids/unique-id");
|
|
24
25
|
/**
|
|
25
26
|
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
@@ -32,6 +33,17 @@ var _uniqueId = require("../../common/ids/unique-id");
|
|
|
32
33
|
|
|
33
34
|
const PROTECTED_KEYS = ['name', 'id', 'type'];
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Warning functions that only fire once - can be reset in tests
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
const warnings = exports.warnings = {
|
|
41
|
+
experimental: (0, _invoke.single)(() => (0, _console.warn)(54, 'newrelic.register')),
|
|
42
|
+
disabled: (0, _invoke.single)(() => (0, _console.warn)(55)),
|
|
43
|
+
invalidTarget: (0, _invoke.single)(target => (0, _console.warn)(48, target)),
|
|
44
|
+
deregistered: (0, _invoke.single)(() => (0, _console.warn)(68))
|
|
45
|
+
};
|
|
46
|
+
|
|
35
47
|
/**
|
|
36
48
|
* @experimental
|
|
37
49
|
* IMPORTANT: This feature is being developed for use internally and is not in a public-facing production-ready state.
|
|
@@ -48,38 +60,41 @@ function setupRegisterAPI(agent) {
|
|
|
48
60
|
* Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
|
|
49
61
|
* @param {Object} agentRef the reference to the base agent instance
|
|
50
62
|
* @param {import('./register-api-types').RegisterAPIConstructor} target
|
|
51
|
-
* @param {import('./register-api-types').RegisterAPIConstructor} [parent]
|
|
52
63
|
* @returns {RegisterAPI} the api object to be returned from the register api method
|
|
53
64
|
*/
|
|
54
|
-
function register(agentRef, target
|
|
55
|
-
|
|
65
|
+
function register(agentRef, target) {
|
|
66
|
+
warnings.experimental();
|
|
56
67
|
target ||= {};
|
|
57
68
|
target.instance = (0, _uniqueId.generateRandomHexString)(8);
|
|
58
|
-
target.type =
|
|
69
|
+
target.type = _utils.V2_TYPES.MFE;
|
|
59
70
|
target.licenseKey ||= agentRef.info.licenseKey; // will inherit the license key from the container agent if not provided for brevity. A future state may dictate that we need different license keys to do different things.
|
|
60
71
|
target.blocked = false;
|
|
61
72
|
if (typeof target.tags !== 'object' || target.tags === null || Array.isArray(target.tags)) target.tags = {};
|
|
62
|
-
target.parent
|
|
73
|
+
target.parent ??= {
|
|
63
74
|
get id() {
|
|
64
75
|
return agentRef.runtime.appMetadata.agents[0].entityGuid;
|
|
65
76
|
},
|
|
66
77
|
// getter because this is asyncronously set
|
|
67
|
-
type:
|
|
78
|
+
type: _utils.V2_TYPES.BA
|
|
68
79
|
};
|
|
69
80
|
const timings = (0, _scriptTracker.findScriptTimings)();
|
|
70
81
|
const attrs = {};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
// Only define attributes getter if it doesn't already exist
|
|
84
|
+
if (!Object.prototype.hasOwnProperty.call(target, 'attributes')) {
|
|
85
|
+
Object.defineProperty(target, 'attributes', {
|
|
86
|
+
get() {
|
|
87
|
+
return {
|
|
88
|
+
...attrs,
|
|
89
|
+
'source.id': target.id,
|
|
90
|
+
'source.name': target.name,
|
|
91
|
+
'source.type': target.type,
|
|
92
|
+
'parent.type': target.parent?.type || _utils.V2_TYPES.BA,
|
|
93
|
+
'parent.id': target.parent?.id
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
83
98
|
|
|
84
99
|
// Process tags object and add to attrs, excluding protected keys
|
|
85
100
|
Object.entries(target.tags).forEach(([key, value]) => {
|
|
@@ -87,23 +102,11 @@ function register(agentRef, target, parent) {
|
|
|
87
102
|
attrs["source.".concat(key)] = value;
|
|
88
103
|
}
|
|
89
104
|
});
|
|
90
|
-
target.isolated ??= true;
|
|
91
105
|
|
|
92
106
|
/** @type {Function} a function that is set and reports when APIs are triggered -- warns the customer of the invalid state */
|
|
93
107
|
let invalidApiResponse = () => {};
|
|
94
108
|
/** @type {Array} the array of registered target APIs */
|
|
95
109
|
const registeredEntities = agentRef.runtime.registeredEntities;
|
|
96
|
-
if (!target.isolated) {
|
|
97
|
-
/** if we have already registered this non-isolated target, go ahead and re-use it */
|
|
98
|
-
const sharedEntity = registeredEntities.find(({
|
|
99
|
-
metadata: {
|
|
100
|
-
target: {
|
|
101
|
-
id
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}) => id === target.id && !target.isolated);
|
|
105
|
-
if (sharedEntity) return sharedEntity;
|
|
106
|
-
}
|
|
107
110
|
|
|
108
111
|
/**
|
|
109
112
|
* Block the API, and supply a warning function to display a message to end users
|
|
@@ -118,8 +121,8 @@ function register(agentRef, target, parent) {
|
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
/** primary cases that can block the register API from working at init time */
|
|
121
|
-
if (!agentRef.init.api.
|
|
122
|
-
if (!hasValidValue(target.id) || !hasValidValue(target.name)) block((
|
|
124
|
+
if (!agentRef.init.api.register.enabled) block(warnings.disabled);
|
|
125
|
+
if (!hasValidValue(target.id) || !hasValidValue(target.name)) block(() => warnings.invalidTarget(target));
|
|
123
126
|
|
|
124
127
|
/** @type {RegisterAPI} */
|
|
125
128
|
const api = {
|
|
@@ -130,7 +133,7 @@ function register(agentRef, target, parent) {
|
|
|
130
133
|
deregister: () => {
|
|
131
134
|
/** note: blocking this instance will disable access for all entities sharing the instance, and will invalidate it from the v2 checks */
|
|
132
135
|
reportTimings();
|
|
133
|
-
block(
|
|
136
|
+
block(warnings.deregistered);
|
|
134
137
|
},
|
|
135
138
|
log: (message, options = {}) => report(_log.log, [message, {
|
|
136
139
|
...options,
|
|
@@ -150,7 +153,6 @@ function register(agentRef, target, parent) {
|
|
|
150
153
|
...attrs,
|
|
151
154
|
...attributes
|
|
152
155
|
}, agentRef], target),
|
|
153
|
-
register: (target = {}) => report(register, [agentRef, target], api.metadata.target),
|
|
154
156
|
recordCustomEvent: (eventType, attributes = {}) => report(_recordCustomEvent.recordCustomEvent, [eventType, {
|
|
155
157
|
...attrs,
|
|
156
158
|
...attributes
|
|
@@ -192,20 +194,24 @@ function register(agentRef, target, parent) {
|
|
|
192
194
|
// only ever report the timings the first time this is called
|
|
193
195
|
if (timings.reportedAt) return;
|
|
194
196
|
timings.reportedAt = (0, _now.now)();
|
|
197
|
+
const timeToFetch = timings.fetchEnd - timings.fetchStart; // fetchStart to fetchEnd
|
|
198
|
+
const timeToExecute = timings.scriptEnd - timings.scriptStart; // scriptStart to scriptEnd
|
|
195
199
|
api.recordCustomEvent('MicroFrontEndTiming', {
|
|
196
200
|
assetUrl: timings.asset,
|
|
197
201
|
// the url of the script that was registered, or undefined if it could not be determined (inline or no match)
|
|
198
202
|
assetType: timings.type,
|
|
199
203
|
// the type of asset that was associated with the timings, one of 'script', 'link' (if preloaded and found in the resource timing buffer), 'preload' (if preloaded but not found in the resource timing buffer), or "unknown" if it could not be determined
|
|
200
|
-
|
|
201
|
-
//
|
|
204
|
+
timeAlive: timings.reportedAt - timings.registeredAt,
|
|
205
|
+
// registeredAt to reportedAt
|
|
202
206
|
timeToBeRequested: timings.fetchStart,
|
|
203
207
|
// origin to fetchStart
|
|
204
|
-
|
|
208
|
+
timeToExecute,
|
|
209
|
+
// scriptStart to scriptEnd
|
|
210
|
+
timeToFetch,
|
|
205
211
|
// fetchStart to fetchEnd
|
|
206
|
-
|
|
207
|
-
//
|
|
208
|
-
|
|
212
|
+
timeToLoad: timeToFetch + timeToExecute,
|
|
213
|
+
// fetch time and script time together
|
|
214
|
+
timeToRegister: timings.registeredAt // timestamp when register() was called
|
|
209
215
|
});
|
|
210
216
|
}
|
|
211
217
|
|
|
@@ -222,7 +228,7 @@ function register(agentRef, target, parent) {
|
|
|
222
228
|
|
|
223
229
|
/**
|
|
224
230
|
* The reporter method that will be used to report the data to the container agent's API method. If invalid, will log a warning and not execute.
|
|
225
|
-
* If the api.
|
|
231
|
+
* If the api.register.duplicate_data_to_container configuration value is set to true, the data will be reported to BOTH the container and the external target
|
|
226
232
|
* @param {*} methodToCall the container agent's API method to call
|
|
227
233
|
* @param {*} args the arguments to supply to the container agent's API method
|
|
228
234
|
* @param {string} target the target to report the data to. If undefined, will report to the container agent's target.
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* @property {boolean} [ajax.enabled] - Turn on/off the ajax feature (on by default).
|
|
13
13
|
* @property {boolean} [ajax.autoStart] - If true, the agent will automatically start the ajax feature. Otherwise, it will be in a deferred state until the `start` API method is called.
|
|
14
14
|
* @property {Object} [api]
|
|
15
|
-
* @property {
|
|
16
|
-
* @property {boolean} [api.
|
|
15
|
+
* @property {Object} [api.register]
|
|
16
|
+
* @property {boolean} [api.register.enabled] - If true, the agent will allow registered children to be sent to the server.
|
|
17
|
+
* @property {boolean} [api.register.duplicate_data_to_container] - If true, the agent will capture registered child data to the main agent as well as the registered child.
|
|
17
18
|
* @property {Object} [distributed_tracing]
|
|
18
19
|
* @property {boolean} [distributed_tracing.enabled] - If true, distributed tracing headers will be added to outgoing requests. Requires ajax feature to be running.
|
|
19
20
|
* @property {boolean} [distributed_tracing.exclude_newrelic_header]
|
|
@@ -21,7 +21,7 @@ const InitModelFn = () => {
|
|
|
21
21
|
const hiddenState = {
|
|
22
22
|
feature_flags: [],
|
|
23
23
|
experimental: {
|
|
24
|
-
|
|
24
|
+
register: false,
|
|
25
25
|
resources: false
|
|
26
26
|
},
|
|
27
27
|
mask_selector: '*',
|
|
@@ -54,13 +54,15 @@ const InitModelFn = () => {
|
|
|
54
54
|
autoStart: true
|
|
55
55
|
},
|
|
56
56
|
api: {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
register: {
|
|
58
|
+
get enabled() {
|
|
59
|
+
return hiddenState.feature_flags.includes(FEATURE_FLAGS.REGISTER) || hiddenState.experimental.register;
|
|
60
|
+
},
|
|
61
|
+
set enabled(val) {
|
|
62
|
+
hiddenState.experimental.register = val;
|
|
63
|
+
},
|
|
64
|
+
duplicate_data_to_container: false
|
|
65
|
+
}
|
|
64
66
|
},
|
|
65
67
|
browser_consent_mode: {
|
|
66
68
|
enabled: false
|
|
@@ -1,9 +1,12 @@
|
|
|
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 { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants';
|
|
5
6
|
import { originTime } from '../constants/runtime';
|
|
6
7
|
import { isNative } from '../util/monkey-patched';
|
|
8
|
+
import { handle } from '../event-emitter/handle';
|
|
9
|
+
import { FEATURE_NAMES } from '../../loaders/features/features';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Class used to adjust the timestamp of harvested data to New Relic server time. This
|
|
@@ -36,11 +39,31 @@ export class TimeKeeper {
|
|
|
36
39
|
* @type {boolean}
|
|
37
40
|
*/
|
|
38
41
|
#ready = false;
|
|
42
|
+
#reportedDrift = false;
|
|
39
43
|
constructor(sessionObj) {
|
|
40
44
|
this.#session = sessionObj;
|
|
41
45
|
this.processStoredDiff();
|
|
42
46
|
isNative(performance.now, Date.now); // will warn the user if these are not native functions. We need these to be native for time in the agent to be accurate in general.
|
|
43
47
|
}
|
|
48
|
+
#detectDrift() {
|
|
49
|
+
if (this.#reportedDrift) return;
|
|
50
|
+
try {
|
|
51
|
+
// Drift detection: measures if performance.now() and Date.now() have become desynchronized
|
|
52
|
+
// This can happen when a machine sleeps and the performance timer freezes while Date continues
|
|
53
|
+
// this can also happen when a user sets their clock forward during the page lifecycle,
|
|
54
|
+
// but we have no way of distinguishing that from actual clock drift so we will just treat it as drift.
|
|
55
|
+
// In either case, the performance timestamps would be inaccurate at that point so we want to detect and report a count of it.
|
|
56
|
+
// We only detect positive drift (performance clock falling behind Date clock)
|
|
57
|
+
// Note: localTimeDiff (server time offset) is NOT part of drift - that's a legitimate offset
|
|
58
|
+
const drift = Date.now() - originTime - performance.now();
|
|
59
|
+
if (drift > 1000) {
|
|
60
|
+
this.#reportedDrift = true;
|
|
61
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/TimeKeeper/ClockDrift/Detected', drift], undefined, FEATURE_NAMES.metrics, this.#session.agentRef.ee);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
// Silently ignore drift detection errors to avoid breaking normal operation
|
|
65
|
+
}
|
|
66
|
+
}
|
|
44
67
|
get ready() {
|
|
45
68
|
return this.#ready;
|
|
46
69
|
}
|
|
@@ -85,6 +108,7 @@ export class TimeKeeper {
|
|
|
85
108
|
* @returns {number} Corrected unix/epoch timestamp
|
|
86
109
|
*/
|
|
87
110
|
convertRelativeTimestamp(relativeTime) {
|
|
111
|
+
this.#detectDrift();
|
|
88
112
|
return originTime + relativeTime;
|
|
89
113
|
}
|
|
90
114
|
|
|
@@ -95,6 +119,7 @@ export class TimeKeeper {
|
|
|
95
119
|
* @returns {number}
|
|
96
120
|
*/
|
|
97
121
|
convertAbsoluteTimestamp(timestamp) {
|
|
122
|
+
this.#detectDrift();
|
|
98
123
|
return timestamp - originTime;
|
|
99
124
|
}
|
|
100
125
|
|
|
@@ -104,6 +129,7 @@ export class TimeKeeper {
|
|
|
104
129
|
* @return {number} Corrected unix/epoch timestamp
|
|
105
130
|
*/
|
|
106
131
|
correctAbsoluteTimestamp(timestamp) {
|
|
132
|
+
this.#detectDrift();
|
|
107
133
|
return timestamp - this.#localTimeDiff;
|
|
108
134
|
}
|
|
109
135
|
|
|
@@ -113,6 +139,7 @@ export class TimeKeeper {
|
|
|
113
139
|
* @returns {number}
|
|
114
140
|
*/
|
|
115
141
|
correctRelativeTimestamp(relativeTime) {
|
|
142
|
+
this.#detectDrift();
|
|
116
143
|
return this.correctAbsoluteTimestamp(this.convertRelativeTimestamp(relativeTime));
|
|
117
144
|
}
|
|
118
145
|
|
|
@@ -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
|
|
|
@@ -62,8 +62,7 @@ export function xhrFetch({
|
|
|
62
62
|
return fetch(url, {
|
|
63
63
|
headers: objHeaders,
|
|
64
64
|
method,
|
|
65
|
-
body
|
|
66
|
-
credentials: 'include'
|
|
65
|
+
body
|
|
67
66
|
});
|
|
68
67
|
}
|
|
69
68
|
|
|
@@ -89,12 +88,6 @@ export function xhr({
|
|
|
89
88
|
}) {
|
|
90
89
|
const request = new XMLHttpRequest();
|
|
91
90
|
request.open(method, url, !sync);
|
|
92
|
-
try {
|
|
93
|
-
// Set cookie
|
|
94
|
-
if ('withCredentials' in request) request.withCredentials = true;
|
|
95
|
-
} catch (e) {
|
|
96
|
-
// do nothing
|
|
97
|
-
}
|
|
98
91
|
headers.forEach(header => {
|
|
99
92
|
request.setRequestHeader(header.key, header.value);
|
|
100
93
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Represents script correlation data combining DOM and Performance API information
|
|
7
|
+
*/
|
|
8
|
+
export class ScriptCorrelation {
|
|
9
|
+
/** @type {CorrelationTiming} [dom] - DOM-related information */
|
|
10
|
+
dom = new CorrelationTiming();
|
|
11
|
+
/** @type {CorrelationTiming} [performance] - Performance-related information */
|
|
12
|
+
performance = new CorrelationTiming();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new ScriptCorrelation instance
|
|
16
|
+
* @param {string} url - The cleaned URL of the script
|
|
17
|
+
*/
|
|
18
|
+
constructor(url) {
|
|
19
|
+
/** @type {string} The cleaned URL of the script */
|
|
20
|
+
this.url = url;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the script timing, using DOM timings if available, otherwise falling back to performance timings or registeredAt as appropriate. This is used to provide the most accurate script timing possible for registered entities.
|
|
25
|
+
* @returns {{start: number, end: number}
|
|
26
|
+
*/
|
|
27
|
+
get script() {
|
|
28
|
+
const start = Math.max(this.dom.start, this.performance.end);
|
|
29
|
+
const end = Math.max(this.dom.end, this.performance.end, start);
|
|
30
|
+
return {
|
|
31
|
+
start,
|
|
32
|
+
end
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
class CorrelationTiming {
|
|
37
|
+
/** @type {number} [start] - The startTime from the performance entry */
|
|
38
|
+
start = 0;
|
|
39
|
+
/** @type {number} [end] - The responseEnd from the performance entry */
|
|
40
|
+
end = 0;
|
|
41
|
+
/** @type {*} [value] - The entry value */
|
|
42
|
+
value = undefined;
|
|
43
|
+
}
|