@newrelic/browser-agent 1.262.0 → 1.263.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 +13 -0
- package/dist/cjs/common/config/state/configurable.js +4 -4
- package/dist/cjs/common/config/state/init.js +5 -3
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/context/shared-context.js +2 -2
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/harvest/harvest.js +1 -1
- package/dist/cjs/common/session/session-entity.js +2 -2
- package/dist/cjs/common/timing/time-keeper.js +13 -2
- package/dist/cjs/common/util/console.js +3 -4
- package/dist/cjs/common/util/obfuscate.js +3 -3
- package/dist/cjs/common/wrap/wrap-logger.js +1 -2
- package/dist/cjs/common/wrap/wrap-xhr.js +1 -1
- package/dist/cjs/features/logging/aggregate/index.js +5 -5
- package/dist/cjs/features/logging/constants.js +2 -5
- package/dist/cjs/features/metrics/aggregate/index.js +16 -0
- package/dist/cjs/features/page_view_event/aggregate/index.js +20 -4
- package/dist/cjs/features/session_replay/aggregate/index.js +1 -1
- package/dist/cjs/features/session_replay/shared/recorder.js +1 -1
- package/dist/cjs/features/spa/aggregate/index.js +1 -1
- package/dist/cjs/features/utils/aggregate-base.js +4 -3
- package/dist/cjs/features/utils/instrument-base.js +2 -2
- package/dist/cjs/loaders/agent-base.js +1 -1
- package/dist/cjs/loaders/agent.js +3 -4
- package/dist/cjs/loaders/api/api.js +9 -7
- package/dist/cjs/loaders/micro-agent.js +5 -5
- package/dist/esm/common/config/state/configurable.js +4 -4
- package/dist/esm/common/config/state/init.js +5 -3
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/context/shared-context.js +2 -2
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/harvest/harvest.js +1 -1
- package/dist/esm/common/session/session-entity.js +2 -2
- package/dist/esm/common/timing/time-keeper.js +12 -2
- package/dist/esm/common/util/console.js +3 -4
- package/dist/esm/common/util/obfuscate.js +3 -3
- package/dist/esm/common/wrap/wrap-logger.js +1 -2
- package/dist/esm/common/wrap/wrap-xhr.js +1 -1
- package/dist/esm/features/logging/aggregate/index.js +6 -6
- package/dist/esm/features/logging/constants.js +1 -4
- package/dist/esm/features/metrics/aggregate/index.js +16 -0
- package/dist/esm/features/page_view_event/aggregate/index.js +21 -5
- package/dist/esm/features/session_replay/aggregate/index.js +1 -1
- package/dist/esm/features/session_replay/shared/recorder.js +1 -1
- package/dist/esm/features/spa/aggregate/index.js +1 -1
- package/dist/esm/features/utils/aggregate-base.js +4 -3
- package/dist/esm/features/utils/instrument-base.js +2 -2
- package/dist/esm/loaders/agent-base.js +1 -1
- package/dist/esm/loaders/agent.js +3 -4
- package/dist/esm/loaders/api/api.js +9 -7
- package/dist/esm/loaders/micro-agent.js +5 -5
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts +2 -1
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
- package/dist/types/common/util/console.d.ts +1 -1
- package/dist/types/common/util/console.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-logger.d.ts.map +1 -1
- package/dist/types/features/logging/constants.d.ts +0 -3
- package/dist/types/features/logging/constants.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/config/state/configurable.js +4 -4
- package/src/common/config/state/init.js +4 -3
- package/src/common/context/shared-context.js +2 -2
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvest.js +1 -1
- package/src/common/session/session-entity.js +2 -2
- package/src/common/timing/time-keeper.js +14 -2
- package/src/common/util/console.js +3 -4
- package/src/common/util/obfuscate.js +3 -3
- package/src/common/wrap/wrap-logger.js +1 -2
- package/src/common/wrap/wrap-xhr.js +1 -1
- package/src/features/logging/aggregate/index.js +6 -6
- package/src/features/logging/constants.js +0 -4
- package/src/features/metrics/aggregate/index.js +12 -0
- package/src/features/page_view_event/aggregate/index.js +22 -5
- package/src/features/session_replay/aggregate/index.js +1 -1
- package/src/features/session_replay/shared/recorder.js +1 -1
- package/src/features/spa/aggregate/index.js +1 -1
- package/src/features/utils/aggregate-base.js +4 -3
- package/src/features/utils/instrument-base.js +2 -2
- package/src/loaders/agent-base.js +1 -1
- package/src/loaders/agent.js +3 -4
- package/src/loaders/api/api.js +9 -7
- package/src/loaders/micro-agent.js +5 -5
|
@@ -58,11 +58,11 @@ export class MicroAgent extends AgentBase {
|
|
|
58
58
|
const featNames = nonAutoFeatures;
|
|
59
59
|
if (features === undefined) features = featNames;else {
|
|
60
60
|
features = Array.isArray(features) && features.length ? features : [features];
|
|
61
|
-
if (features.some(f => !featNames.includes(f))) return warn(
|
|
61
|
+
if (features.some(f => !featNames.includes(f))) return warn(37, featNames);
|
|
62
62
|
if (!features.includes(FEATURE_NAMES.pageViewEvent)) features.push(FEATURE_NAMES.pageViewEvent);
|
|
63
63
|
}
|
|
64
64
|
} catch (err) {
|
|
65
|
-
warn(
|
|
65
|
+
warn(23, err);
|
|
66
66
|
}
|
|
67
67
|
try {
|
|
68
68
|
const enabledFeatures = getEnabledFeatures(this.agentIdentifier);
|
|
@@ -70,7 +70,7 @@ export class MicroAgent extends AgentBase {
|
|
|
70
70
|
// a biproduct of doing this is that the "session manager" is automatically handled through importing this feature
|
|
71
71
|
this.features.page_view_event = new PVE(this.agentIdentifier, this.sharedAggregator);
|
|
72
72
|
} catch (err) {
|
|
73
|
-
warn(
|
|
73
|
+
warn(24, err);
|
|
74
74
|
}
|
|
75
75
|
onWindowLoad(() => {
|
|
76
76
|
// these features do not import an "instrument" file, meaning they are only hooked up to the API.
|
|
@@ -86,13 +86,13 @@ export class MicroAgent extends AgentBase {
|
|
|
86
86
|
Aggregate
|
|
87
87
|
} = _ref2;
|
|
88
88
|
this.features[f] = new Aggregate(this.agentIdentifier, this.sharedAggregator);
|
|
89
|
-
}).catch(err => warn(
|
|
89
|
+
}).catch(err => warn(25, err));
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
return true;
|
|
94
94
|
} catch (err) {
|
|
95
|
-
warn(
|
|
95
|
+
warn(26, err);
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/common/config/state/init.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/common/config/state/init.js"],"names":[],"mappings":"AAiHA,+CAIC;AAED,0DAKC;AAED,+DAYC"}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export class TimeKeeper {
|
|
7
7
|
constructor(agentIdentifier: any);
|
|
8
|
-
get ready():
|
|
8
|
+
get ready(): boolean;
|
|
9
9
|
get correctedOriginTime(): number;
|
|
10
|
+
get localTimeDiff(): number;
|
|
10
11
|
/**
|
|
11
12
|
* Process a rum request to calculate NR server time.
|
|
12
13
|
* @param rumRequest {XMLHttpRequest} The xhr for the rum request
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IA2BE,kCAGC;IAED,qBAEC;IAED,kCAEC;IAED,4BAEC;IAED;;;;;OAKG;IACH,8BAJsB,cAAc,aACf,MAAM,WACR,MAAM,QA2BxB;IAED;;;;;OAKG;IACH,uCAHwB,MAAM,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oCAHqB,MAAM,GACf,MAAM,CAIjB;IAED,+FAA+F;IAC/F,0BASC;;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../../src/common/util/console.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../../src/common/util/console.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,4CAHW,GAAC,QAMX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"AAcA;;;;;;GAMG;AAEH,qCANW,MAAM,UACN,MAAM,YACN,MAAM,iBACJ,MAAM,CAoBlB;AAED;;;;;;GAMG;AACH,mCAJW,MAAM,GAEJ,MAAM,CAIlB"}
|
|
@@ -8,7 +8,4 @@ export namespace LOG_LEVELS {
|
|
|
8
8
|
export const LOGGING_EVENT_EMITTER_CHANNEL: "log";
|
|
9
9
|
export const FEATURE_NAME: string;
|
|
10
10
|
export const MAX_PAYLOAD_SIZE: 1000000;
|
|
11
|
-
export const LOGGING_FAILURE_MESSAGE: "failed to wrap logger: ";
|
|
12
|
-
export const LOGGING_LEVEL_FAILURE_MESSAGE: "invalid log level: ";
|
|
13
|
-
export const LOGGING_IGNORED: "ignored log: ";
|
|
14
11
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/logging/constants.js"],"names":[],"mappings":";;;;;;;AAUA,kDAAkD;AAElD,kCAAiD;AAEjD,uCAAuC
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/logging/constants.js"],"names":[],"mappings":";;;;;;;AAUA,kDAAkD;AAElD,kCAAiD;AAEjD,uCAAuC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAaA;IACE,2BAAiC;IACjC,mDAsBC;IAED,wDAKC;IAED,iDAKC;IAED,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAaA;IACE,2BAAiC;IACjC,mDAsBC;IAED,wDAKC;IAED,iDAKC;IAED,qBAyDC;IAED,0BAOC;IAED,eAkCC;IA/BG,mCAAyB;CAgC9B;8BAlJ6B,4BAA4B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_event/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAA2C;IAC3C,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_event/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAA2C;IAC3C,mDA0BC;IAvBC,wBAAwB;IACxB,8BAA8B;IAC9B,8BAA8B;IAC9B,uBAAsD;IAsBxD,gBAkHC;CACF;8BA5J6B,4BAA4B;2BAS/B,oCAAoC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAYA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAYA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAAqI;IACrI,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAsCC;IAED;;;;;OAKG;IACH,aAHW,GAAC,cACD,GAAC,QA4BX;IAED,0HAA0H;IAC1H,yCAqDC;IA3CG,8BAAoB;IA6CxB,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BA3N8B,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAOA;IACE,4BAGC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAsBlB;IAED,cAGC;IADC,6BAAmB;IAGrB;;;OAGG;IACH,
|
|
1
|
+
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAOA;IACE,4BAGC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAsBlB;IAED,cAGC;IADC,6BAAmB;IAGrB;;;OAGG;IACH,2BAsBC;CACF;4BAvE2B,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAiBA;;;GAGG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,wCA2BhB;IAdC,yCAAiF;IACjF,yBAAkB;IAGlB,sCAAsD;IAMtD,uCAA6G;IAM/G;;;;;MAOC;IAED,yBAiCC;CACF;0BA3FyB,cAAc;2BAQb,gCAAgC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAsBA,2CAiBC;AAID;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAsBA,2CAiBC;AAID;;;;;;;;;;;;IAiEE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@ import { warn } from '../../util/console'
|
|
|
2
2
|
|
|
3
3
|
export function getModeledObject (obj, model) {
|
|
4
4
|
try {
|
|
5
|
-
if (!obj || typeof obj !== 'object') return warn(
|
|
6
|
-
if (!model || typeof model !== 'object') return warn(
|
|
5
|
+
if (!obj || typeof obj !== 'object') return warn(3)
|
|
6
|
+
if (!model || typeof model !== 'object') return warn(4)
|
|
7
7
|
// allow getters and setters to pass from model to target
|
|
8
8
|
const output = Object.create(
|
|
9
9
|
Object.getPrototypeOf(model),
|
|
@@ -19,11 +19,11 @@ export function getModeledObject (obj, model) {
|
|
|
19
19
|
else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key])
|
|
20
20
|
else output[key] = obj[key]
|
|
21
21
|
} catch (e) {
|
|
22
|
-
warn(
|
|
22
|
+
warn(1, e)
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
return output
|
|
26
26
|
} catch (err) {
|
|
27
|
-
warn(
|
|
27
|
+
warn(2, err)
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -69,6 +69,7 @@ const model = () => {
|
|
|
69
69
|
collect_fonts: false, // serialize fonts for collection without public asset url, this is currently broken in RRWeb -- https://github.com/rrweb-io/rrweb/issues/1304. When fixed, revisit with test cases
|
|
70
70
|
inline_images: false, // serialize images for collection without public asset url -- right now this is only useful for testing as it easily generates payloads too large to be harvested
|
|
71
71
|
inline_stylesheet: true, // serialize css for collection without public asset url
|
|
72
|
+
fix_stylesheets: true, // fetch missing stylesheet resources for inlining, only works if 'inline_stylesheet' is also true
|
|
72
73
|
// recording config settings
|
|
73
74
|
mask_all_inputs: true,
|
|
74
75
|
// this has a getter/setter to facilitate validation of the selectors
|
|
@@ -76,7 +77,7 @@ const model = () => {
|
|
|
76
77
|
set mask_text_selector (val) {
|
|
77
78
|
if (isValidSelector(val)) hiddenState.mask_selector = `${val},${nrMask}`
|
|
78
79
|
else if (val === '' || val === null) hiddenState.mask_selector = nrMask
|
|
79
|
-
else warn(
|
|
80
|
+
else warn(5, val)
|
|
80
81
|
},
|
|
81
82
|
// these properties only have getters because they are enforcable constants and should error if someone tries to override them
|
|
82
83
|
get block_class () { return 'nr-block' },
|
|
@@ -89,7 +90,7 @@ const model = () => {
|
|
|
89
90
|
},
|
|
90
91
|
set block_selector (val) {
|
|
91
92
|
if (isValidSelector(val)) hiddenState.block_selector += `,${val}`
|
|
92
|
-
else if (val !== '') warn(
|
|
93
|
+
else if (val !== '') warn(6, val)
|
|
93
94
|
},
|
|
94
95
|
// password: must always be present and true no matter what customer sets
|
|
95
96
|
get mask_input_options () {
|
|
@@ -97,7 +98,7 @@ const model = () => {
|
|
|
97
98
|
},
|
|
98
99
|
set mask_input_options (val) {
|
|
99
100
|
if (val && typeof val === 'object') hiddenState.mask_input_options = { ...val, password: true }
|
|
100
|
-
else warn(
|
|
101
|
+
else warn(7, val)
|
|
101
102
|
}
|
|
102
103
|
},
|
|
103
104
|
session_trace: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
|
|
@@ -8,14 +8,14 @@ const model = {
|
|
|
8
8
|
export class SharedContext {
|
|
9
9
|
constructor (context) {
|
|
10
10
|
try {
|
|
11
|
-
if (typeof context !== 'object') return warn(
|
|
11
|
+
if (typeof context !== 'object') return warn(8)
|
|
12
12
|
this.sharedContext = {}
|
|
13
13
|
Object.assign(this.sharedContext, model)
|
|
14
14
|
Object.entries(context).forEach(([key, value]) => {
|
|
15
15
|
if (Object.keys(model).includes(key)) this.sharedContext[key] = value
|
|
16
16
|
})
|
|
17
17
|
} catch (err) {
|
|
18
|
-
warn(
|
|
18
|
+
warn(9, err)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -90,7 +90,7 @@ function checkCanDrainAll (agentIdentifier) {
|
|
|
90
90
|
function drainGroup (agentIdentifier, group, activateGroup = true) {
|
|
91
91
|
const baseEE = agentIdentifier ? ee.get(agentIdentifier) : ee
|
|
92
92
|
const handlers = defaultRegister.handlers // other storage in registerHandler
|
|
93
|
-
if (!baseEE.backlog || !handlers) return
|
|
93
|
+
if (baseEE.aborted || !baseEE.backlog || !handlers) return
|
|
94
94
|
|
|
95
95
|
// Only activated features being drained should run queued listeners on buffered events. Deactivated features only need to release memory.
|
|
96
96
|
if (activateGroup) {
|
|
@@ -122,7 +122,7 @@ export class Harvest extends SharedContext {
|
|
|
122
122
|
body = stringify(body)
|
|
123
123
|
}
|
|
124
124
|
/** Warn --once per endpoint-- if the agent tries to send large payloads */
|
|
125
|
-
if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(
|
|
125
|
+
if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(28, endpoint)
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
if (!body || body.length === 0 || body === '{}' || body === '[]') {
|
|
@@ -182,7 +182,7 @@ export class SessionEntity {
|
|
|
182
182
|
|
|
183
183
|
return obj
|
|
184
184
|
} catch (e) {
|
|
185
|
-
warn(
|
|
185
|
+
warn(10, e)
|
|
186
186
|
// storage is inaccessible
|
|
187
187
|
return {}
|
|
188
188
|
}
|
|
@@ -208,7 +208,7 @@ export class SessionEntity {
|
|
|
208
208
|
return data
|
|
209
209
|
} catch (e) {
|
|
210
210
|
// storage is inaccessible
|
|
211
|
-
warn(
|
|
211
|
+
warn(11, e)
|
|
212
212
|
return null
|
|
213
213
|
}
|
|
214
214
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { originTime } from '../constants/runtime'
|
|
2
2
|
import { getRuntime } from '../config/config'
|
|
3
3
|
|
|
4
|
+
const rfc2616Regex = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0-3][0-9]) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) ([01][0-9]|2[0-3])(:[0-5][0-9]){2} GMT$/
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Class used to adjust the timestamp of harvested data to New Relic server time. This
|
|
6
8
|
* is done by tracking the performance timings of the RUM call and applying a calculation
|
|
@@ -29,7 +31,7 @@ export class TimeKeeper {
|
|
|
29
31
|
/**
|
|
30
32
|
* Represents whether the timekeeper is in a state that it can accurately convert
|
|
31
33
|
* timestamps.
|
|
32
|
-
* @type {
|
|
34
|
+
* @type {boolean}
|
|
33
35
|
*/
|
|
34
36
|
#ready = false
|
|
35
37
|
|
|
@@ -46,6 +48,10 @@ export class TimeKeeper {
|
|
|
46
48
|
return this.#correctedOriginTime
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
get localTimeDiff () {
|
|
52
|
+
return this.#localTimeDiff
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
/**
|
|
50
56
|
* Process a rum request to calculate NR server time.
|
|
51
57
|
* @param rumRequest {XMLHttpRequest} The xhr for the rum request
|
|
@@ -53,12 +59,16 @@ export class TimeKeeper {
|
|
|
53
59
|
* @param endTime {number} The end time of the RUM request
|
|
54
60
|
*/
|
|
55
61
|
processRumRequest (rumRequest, startTime, endTime) {
|
|
56
|
-
this.processStoredDiff()
|
|
62
|
+
this.processStoredDiff() // Check session entity for stored time diff
|
|
57
63
|
if (this.#ready) return // Server time calculated from session entity
|
|
64
|
+
|
|
58
65
|
const responseDateHeader = rumRequest.getResponseHeader('Date')
|
|
59
66
|
if (!responseDateHeader) {
|
|
60
67
|
throw new Error('Missing date header on rum response.')
|
|
61
68
|
}
|
|
69
|
+
if (!rfc2616Regex.test(responseDateHeader)) {
|
|
70
|
+
throw new Error('Date header invalid format.')
|
|
71
|
+
}
|
|
62
72
|
|
|
63
73
|
const medianRumOffset = (endTime - startTime) / 2
|
|
64
74
|
const serverOffset = startTime + medianRumOffset
|
|
@@ -96,6 +106,8 @@ export class TimeKeeper {
|
|
|
96
106
|
|
|
97
107
|
/** Process the session entity and use the info to set the main time calculations if present */
|
|
98
108
|
processStoredDiff () {
|
|
109
|
+
if (this.#ready) return // Time diff has already been calculated
|
|
110
|
+
|
|
99
111
|
const storedServerTimeDiff = this.#session?.read()?.serverTimeDiff
|
|
100
112
|
if (typeof storedServerTimeDiff === 'number' && !isNaN(storedServerTimeDiff)) {
|
|
101
113
|
this.#localTimeDiff = storedServerTimeDiff
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* @param {*} [secondary] Secondary data to include, usually an error or object
|
|
5
5
|
* @returns
|
|
6
6
|
*/
|
|
7
|
-
export function warn (
|
|
8
|
-
if (typeof console.
|
|
9
|
-
console.
|
|
10
|
-
if (secondary) console.warn(secondary)
|
|
7
|
+
export function warn (code, secondary) {
|
|
8
|
+
if (typeof console.debug !== 'function') return
|
|
9
|
+
console.debug(`New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/docs/warning-codes.md#${code}`, secondary)
|
|
11
10
|
}
|
|
@@ -49,16 +49,16 @@ export function validateRules (rules) {
|
|
|
49
49
|
var invalidRegexDetected = false
|
|
50
50
|
for (var i = 0; i < rules.length; i++) {
|
|
51
51
|
if (!('regex' in rules[i])) {
|
|
52
|
-
warn(
|
|
52
|
+
warn(12)
|
|
53
53
|
invalidRegexDetected = true
|
|
54
54
|
} else if (typeof rules[i].regex !== 'string' && !(rules[i].regex instanceof RegExp)) {
|
|
55
|
-
warn(
|
|
55
|
+
warn(13)
|
|
56
56
|
invalidRegexDetected = true
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
var replacement = rules[i].replacement
|
|
60
60
|
if (replacement && typeof replacement !== 'string') {
|
|
61
|
-
warn(
|
|
61
|
+
warn(14)
|
|
62
62
|
invalidReplacementDetected = true
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* This module is used by: jserrors, spa.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { LOGGING_FAILURE_MESSAGE } from '../../features/logging/constants'
|
|
11
10
|
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
|
|
12
11
|
import { EventContext } from '../event-emitter/event-context'
|
|
13
12
|
import { warn } from '../util/console'
|
|
@@ -22,7 +21,7 @@ import { createWrapperWithEmitter as wfn } from './wrap-function'
|
|
|
22
21
|
*/
|
|
23
22
|
// eslint-disable-next-line
|
|
24
23
|
export function wrapLogger(sharedEE, parent, loggerFn, context) {
|
|
25
|
-
if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return warn(
|
|
24
|
+
if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return warn(29)
|
|
26
25
|
const ee = scopedEE(sharedEE)
|
|
27
26
|
const wrapFn = wfn(ee)
|
|
28
27
|
|
|
@@ -56,7 +56,7 @@ export function wrapXhr (sharedEE) {
|
|
|
56
56
|
ee.emit('new-xhr', [xhr], context)
|
|
57
57
|
xhr.addEventListener(READY_STATE_CHANGE, wrapXHR(context), eventListenerOpts(false))
|
|
58
58
|
} catch (e) {
|
|
59
|
-
warn(
|
|
59
|
+
warn(15, e)
|
|
60
60
|
try {
|
|
61
61
|
ee.emit('internal-error', [e])
|
|
62
62
|
} catch (err) {
|
|
@@ -6,7 +6,7 @@ import { warn } from '../../../common/util/console'
|
|
|
6
6
|
import { stringify } from '../../../common/util/stringify'
|
|
7
7
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
8
8
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
9
|
-
import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL,
|
|
9
|
+
import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL, LOG_LEVELS, MAX_PAYLOAD_SIZE } from '../constants'
|
|
10
10
|
import { Log } from '../shared/log'
|
|
11
11
|
import { isValidLogLevel } from '../shared/utils'
|
|
12
12
|
|
|
@@ -49,7 +49,7 @@ export class Aggregate extends AggregateBase {
|
|
|
49
49
|
|
|
50
50
|
if (!attributes || typeof attributes !== 'object') attributes = {}
|
|
51
51
|
if (typeof level === 'string') level = level.toUpperCase()
|
|
52
|
-
if (!isValidLogLevel(level)) return warn(
|
|
52
|
+
if (!isValidLogLevel(level)) return warn(30, level)
|
|
53
53
|
|
|
54
54
|
try {
|
|
55
55
|
if (typeof message !== 'string') {
|
|
@@ -63,13 +63,13 @@ export class Aggregate extends AggregateBase {
|
|
|
63
63
|
else message = String(message)
|
|
64
64
|
}
|
|
65
65
|
} catch (err) {
|
|
66
|
-
warn(
|
|
66
|
+
warn(16, message)
|
|
67
67
|
return
|
|
68
68
|
}
|
|
69
|
-
if (typeof message !== 'string' || !message) return warn(
|
|
69
|
+
if (typeof message !== 'string' || !message) return warn(32)
|
|
70
70
|
if (message.length > MAX_PAYLOAD_SIZE) {
|
|
71
71
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', message.length])
|
|
72
|
-
return warn(
|
|
72
|
+
return warn(31, message.slice(0, 25) + '...')
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
const log = new Log(
|
|
@@ -81,7 +81,7 @@ export class Aggregate extends AggregateBase {
|
|
|
81
81
|
const logBytes = log.message.length + stringify(log.attributes).length + log.level.length + 10 // timestamp == 10 chars
|
|
82
82
|
if (logBytes > MAX_PAYLOAD_SIZE) {
|
|
83
83
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', logBytes])
|
|
84
|
-
return warn(
|
|
84
|
+
return warn(31, log.message.slice(0, 25) + '...')
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
if (this.estimatedBytes + logBytes >= MAX_PAYLOAD_SIZE) {
|
|
@@ -13,7 +13,3 @@ export const LOGGING_EVENT_EMITTER_CHANNEL = 'log'
|
|
|
13
13
|
export const FEATURE_NAME = FEATURE_NAMES.logging
|
|
14
14
|
|
|
15
15
|
export const MAX_PAYLOAD_SIZE = 1000000
|
|
16
|
-
|
|
17
|
-
export const LOGGING_FAILURE_MESSAGE = 'failed to wrap logger: '
|
|
18
|
-
export const LOGGING_LEVEL_FAILURE_MESSAGE = 'invalid log level: '
|
|
19
|
-
export const LOGGING_IGNORED = 'ignored log: '
|
|
@@ -96,6 +96,18 @@ export class Aggregate extends AggregateBase {
|
|
|
96
96
|
// Check if proxy for either chunks or beacon is being used
|
|
97
97
|
if (proxy.assets) this.storeSupportabilityMetrics('Config/AssetsUrl/Changed')
|
|
98
98
|
if (proxy.beacon) this.storeSupportabilityMetrics('Config/BeaconUrl/Changed')
|
|
99
|
+
|
|
100
|
+
if (isBrowserScope && window.MutationObserver) {
|
|
101
|
+
this.storeSupportabilityMetrics('Generic/VideoElement/Added', window.document.querySelectorAll('video').length)
|
|
102
|
+
const mo = new MutationObserver(records => {
|
|
103
|
+
records.forEach(record => {
|
|
104
|
+
record.addedNodes.forEach(addedNode => {
|
|
105
|
+
if (addedNode instanceof HTMLVideoElement) { this.storeSupportabilityMetrics('Generic/VideoElement/Added', 1) }
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
mo.observe(window.document.body, { childList: true, subtree: true })
|
|
110
|
+
}
|
|
99
111
|
}
|
|
100
112
|
|
|
101
113
|
eachSessionChecks () {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { globalScope, isBrowserScope, originTime } from '../../../common/constants/runtime'
|
|
2
2
|
import { addPT, addPN } from '../../../common/timing/nav-timing'
|
|
3
3
|
import { stringify } from '../../../common/util/stringify'
|
|
4
|
-
import { getInfo, getRuntime } from '../../../common/config/config'
|
|
4
|
+
import { getInfo, getRuntime, isConfigured } from '../../../common/config/config'
|
|
5
5
|
import { Harvest } from '../../../common/harvest/harvest'
|
|
6
6
|
import * as CONSTANTS from '../constants'
|
|
7
7
|
import { getActivatedFeaturesFlags } from './initialized-features'
|
|
@@ -28,6 +28,11 @@ export class Aggregate extends AggregateBase {
|
|
|
28
28
|
this.firstByteToDomContent = 0 // our "dom processing" duration
|
|
29
29
|
this.timeKeeper = new TimeKeeper(this.agentIdentifier)
|
|
30
30
|
|
|
31
|
+
if (!isConfigured(agentIdentifier)) {
|
|
32
|
+
this.ee.abort()
|
|
33
|
+
return warn(43)
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
if (isBrowserScope) {
|
|
32
37
|
timeToFirstByte.subscribe(({ value, attrs }) => {
|
|
33
38
|
const navEntry = attrs.navigationEntry
|
|
@@ -48,7 +53,6 @@ export class Aggregate extends AggregateBase {
|
|
|
48
53
|
const agentRuntime = getRuntime(this.agentIdentifier)
|
|
49
54
|
const harvester = new Harvest(this)
|
|
50
55
|
|
|
51
|
-
if (!info.beacon) return
|
|
52
56
|
if (info.queueTime) this.aggregator.store('measures', 'qt', { value: info.queueTime })
|
|
53
57
|
if (info.applicationTime) this.aggregator.store('measures', 'ap', { value: info.applicationTime })
|
|
54
58
|
|
|
@@ -126,11 +130,24 @@ export class Aggregate extends AggregateBase {
|
|
|
126
130
|
if (!this.timeKeeper.ready) throw new Error('TimeKeeper not ready')
|
|
127
131
|
|
|
128
132
|
agentRuntime.timeKeeper = this.timeKeeper
|
|
133
|
+
|
|
134
|
+
// Check if the time diff is such that we need to capture a supportability metric
|
|
135
|
+
if (this.timeKeeper.localTimeDiff >= 12 * 60 * 60 * 1000) {
|
|
136
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed12Hrs'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
137
|
+
} else if (this.timeKeeper.localTimeDiff >= 6 * 60 * 60 * 1000) {
|
|
138
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed6Hrs'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
139
|
+
} else if (this.timeKeeper.localTimeDiff >= 60 * 60 * 1000) {
|
|
140
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed1Hrs'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
141
|
+
}
|
|
129
142
|
} catch (error) {
|
|
130
|
-
|
|
143
|
+
if (error?.message?.indexOf('invalid format') > 0) {
|
|
144
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/InvalidFormat'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
145
|
+
} else {
|
|
146
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
147
|
+
}
|
|
131
148
|
drain(this.agentIdentifier, FEATURE_NAMES.metrics, true)
|
|
132
149
|
this.ee.abort()
|
|
133
|
-
warn(
|
|
150
|
+
warn(17, error)
|
|
134
151
|
return
|
|
135
152
|
}
|
|
136
153
|
|
|
@@ -141,7 +158,7 @@ export class Aggregate extends AggregateBase {
|
|
|
141
158
|
this.drain()
|
|
142
159
|
} catch (err) {
|
|
143
160
|
this.ee.abort()
|
|
144
|
-
warn(
|
|
161
|
+
warn(18, err)
|
|
145
162
|
}
|
|
146
163
|
}
|
|
147
164
|
})
|
|
@@ -394,7 +394,7 @@ export class Aggregate extends AggregateBase {
|
|
|
394
394
|
|
|
395
395
|
/** Abort the feature, once aborted it will not resume */
|
|
396
396
|
abort (reason = {}, data) {
|
|
397
|
-
warn(
|
|
397
|
+
warn(33, reason.message)
|
|
398
398
|
handle(SUPPORTABILITY_METRIC_CHANNEL, [`SessionReplay/Abort/${reason.sm}`, data], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
399
399
|
this.blocked = true
|
|
400
400
|
this.mode = MODE.OFF
|
|
@@ -35,7 +35,7 @@ export class Recorder {
|
|
|
35
35
|
/** Config to inform to inline stylesheet contents (true default) */
|
|
36
36
|
this.shouldInlineStylesheets = getConfigurationValue(this.parent.agentIdentifier, 'session_replay.inline_stylesheet')
|
|
37
37
|
/** A flag that can be set to false by failing conversions to stop the fetching process */
|
|
38
|
-
this.shouldFix = this.shouldInlineStylesheets
|
|
38
|
+
this.shouldFix = this.shouldInlineStylesheets && getConfigurationValue(this.parent.agentIdentifier, 'session_replay.fix_stylesheets')
|
|
39
39
|
/** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
|
|
40
40
|
this.stopRecording = () => { /* no-op until set by rrweb initializer */ }
|
|
41
41
|
}
|
|
@@ -757,7 +757,7 @@ export class Aggregate extends AggregateBase {
|
|
|
757
757
|
handle(SUPPORTABILITY_METRIC_CHANNEL, [`Spa/Interaction/${smCategory}/Duration/Ms`, Math.max((interaction.root?.end || 0) - (interaction.root?.start || 0), 0)], undefined, FEATURE_NAMES.metrics, baseEE)
|
|
758
758
|
|
|
759
759
|
scheduler?.scheduleHarvest(0)
|
|
760
|
-
if (!scheduler) warn(
|
|
760
|
+
if (!scheduler) warn(19)
|
|
761
761
|
}
|
|
762
762
|
|
|
763
763
|
function isEnabled () {
|
|
@@ -49,7 +49,8 @@ export class AggregateBase extends FeatureBase {
|
|
|
49
49
|
checkConfiguration () {
|
|
50
50
|
// NOTE: This check has to happen at aggregator load time
|
|
51
51
|
if (!isConfigured(this.agentIdentifier)) {
|
|
52
|
-
|
|
52
|
+
const cdn = gosCDN()
|
|
53
|
+
let jsAttributes = { ...cdn.info?.jsAttributes }
|
|
53
54
|
try {
|
|
54
55
|
jsAttributes = {
|
|
55
56
|
...jsAttributes,
|
|
@@ -59,9 +60,9 @@ export class AggregateBase extends FeatureBase {
|
|
|
59
60
|
// do nothing
|
|
60
61
|
}
|
|
61
62
|
configure({ agentIdentifier: this.agentIdentifier }, {
|
|
62
|
-
...
|
|
63
|
+
...cdn,
|
|
63
64
|
info: {
|
|
64
|
-
...
|
|
65
|
+
...cdn.info,
|
|
65
66
|
jsAttributes
|
|
66
67
|
},
|
|
67
68
|
runtime: getRuntime(this.agentIdentifier)
|
|
@@ -85,7 +85,7 @@ export class InstrumentBase extends FeatureBase {
|
|
|
85
85
|
session = setupAgentSession(this.agentIdentifier)
|
|
86
86
|
}
|
|
87
87
|
} catch (e) {
|
|
88
|
-
warn(
|
|
88
|
+
warn(20, e)
|
|
89
89
|
this.ee.emit('internal-error', [e])
|
|
90
90
|
if (this.featureName === FEATURE_NAMES.sessionReplay) this.abortHandler?.() // SR should stop recording if session DNE
|
|
91
91
|
}
|
|
@@ -105,7 +105,7 @@ export class InstrumentBase extends FeatureBase {
|
|
|
105
105
|
this.featAggregate = new Aggregate(this.agentIdentifier, this.aggregator, argsObjFromInstrument)
|
|
106
106
|
loadedSuccessfully(true)
|
|
107
107
|
} catch (e) {
|
|
108
|
-
warn(
|
|
108
|
+
warn(34, e)
|
|
109
109
|
this.abortHandler?.() // undo any important alterations made to the page
|
|
110
110
|
// not supported yet but nice to do: "abort" this agent's EE for this feature specifically
|
|
111
111
|
drain(this.agentIdentifier, this.featureName, true)
|
|
@@ -25,7 +25,7 @@ export class AgentBase {
|
|
|
25
25
|
* @param {...any} args
|
|
26
26
|
*/
|
|
27
27
|
#callMethod (methodName, ...args) {
|
|
28
|
-
if (typeof this.api?.[methodName] !== 'function') warn(
|
|
28
|
+
if (typeof this.api?.[methodName] !== 'function') warn(35, methodName)
|
|
29
29
|
else return this.api[methodName](...args)
|
|
30
30
|
}
|
|
31
31
|
|
package/src/loaders/agent.js
CHANGED
|
@@ -13,7 +13,6 @@ import { Instrument as PageViewEvent } from '../features/page_view_event/instrum
|
|
|
13
13
|
import { Aggregator } from '../common/aggregate/aggregator'
|
|
14
14
|
import { gosNREUM, setNREUMInitializedAgent } from '../common/window/nreum'
|
|
15
15
|
import { warn } from '../common/util/console'
|
|
16
|
-
import { stringify } from '../common/util/stringify'
|
|
17
16
|
import { globalScope } from '../common/constants/runtime'
|
|
18
17
|
|
|
19
18
|
/**
|
|
@@ -31,7 +30,7 @@ export class Agent extends AgentBase {
|
|
|
31
30
|
if (!globalScope) {
|
|
32
31
|
// We could not determine the runtime environment. Short-circuite the agent here
|
|
33
32
|
// to avoid possible exceptions later that may cause issues with customer's application.
|
|
34
|
-
warn(
|
|
33
|
+
warn(21)
|
|
35
34
|
return
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -74,12 +73,12 @@ export class Agent extends AgentBase {
|
|
|
74
73
|
|
|
75
74
|
const dependencies = getFeatureDependencyNames(InstrumentCtor.featureName)
|
|
76
75
|
const hasAllDeps = dependencies.every(featName => featName in this.features) // any other feature(s) this depends on should've been initialized on prior iterations by priority order
|
|
77
|
-
if (!hasAllDeps) warn(
|
|
76
|
+
if (!hasAllDeps) warn(36, InstrumentCtor.featureName)
|
|
78
77
|
|
|
79
78
|
this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator)
|
|
80
79
|
})
|
|
81
80
|
} catch (err) {
|
|
82
|
-
warn(
|
|
81
|
+
warn(22, err)
|
|
83
82
|
for (const featName in this.features) { // this.features hold only features that have been instantiated
|
|
84
83
|
this.features[featName].abortHandler?.()
|
|
85
84
|
}
|