@newrelic/browser-agent 1.276.0 → 1.278.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 +19 -0
- package/dist/cjs/common/aggregate/event-aggregator.js +1 -1
- package/dist/cjs/common/config/init.js +1 -10
- package/dist/cjs/common/config/runtime.js +2 -1
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +255 -0
- package/dist/cjs/common/harvest/types.js +5 -21
- package/dist/cjs/features/ajax/aggregate/index.js +2 -11
- package/dist/cjs/features/generic_events/aggregate/index.js +17 -13
- package/dist/cjs/features/generic_events/constants.js +2 -1
- package/dist/cjs/features/jserrors/aggregate/index.js +3 -14
- package/dist/cjs/features/logging/aggregate/index.js +4 -12
- package/dist/cjs/features/metrics/aggregate/index.js +7 -15
- package/dist/cjs/features/page_view_event/aggregate/index.js +46 -48
- package/dist/cjs/features/page_view_timing/aggregate/index.js +0 -9
- package/dist/cjs/features/session_replay/aggregate/index.js +21 -43
- package/dist/cjs/features/session_replay/instrument/index.js +2 -1
- package/dist/cjs/features/session_replay/shared/recorder.js +6 -6
- package/dist/cjs/features/session_trace/aggregate/index.js +9 -24
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +8 -2
- package/dist/cjs/features/soft_navigations/aggregate/index.js +31 -21
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +2 -1
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +12 -12
- package/dist/cjs/features/soft_navigations/constants.js +5 -2
- package/dist/cjs/features/spa/aggregate/index.js +7 -10
- package/dist/cjs/features/utils/aggregate-base.js +66 -27
- package/dist/cjs/features/utils/event-buffer.js +0 -1
- package/dist/cjs/features/utils/event-store-manager.js +109 -0
- package/dist/cjs/features/utils/instrument-base.js +1 -10
- package/dist/cjs/loaders/api/api-methods.js +1 -1
- package/dist/cjs/loaders/api/api.js +2 -1
- package/dist/cjs/loaders/features/features.js +16 -10
- package/dist/cjs/loaders/micro-agent-base.js +10 -0
- package/dist/cjs/loaders/micro-agent.js +1 -0
- package/dist/esm/common/aggregate/event-aggregator.js +1 -1
- package/dist/esm/common/config/init.js +1 -10
- package/dist/esm/common/config/runtime.js +2 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvester.js +249 -0
- package/dist/esm/common/harvest/types.js +5 -21
- package/dist/esm/features/ajax/aggregate/index.js +3 -12
- package/dist/esm/features/generic_events/aggregate/index.js +18 -14
- package/dist/esm/features/generic_events/constants.js +1 -0
- package/dist/esm/features/jserrors/aggregate/index.js +4 -15
- package/dist/esm/features/logging/aggregate/index.js +4 -12
- package/dist/esm/features/metrics/aggregate/index.js +7 -15
- package/dist/esm/features/page_view_event/aggregate/index.js +46 -48
- package/dist/esm/features/page_view_timing/aggregate/index.js +1 -10
- package/dist/esm/features/session_replay/aggregate/index.js +22 -44
- package/dist/esm/features/session_replay/instrument/index.js +2 -1
- package/dist/esm/features/session_replay/shared/recorder.js +6 -6
- package/dist/esm/features/session_trace/aggregate/index.js +9 -24
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +8 -2
- package/dist/esm/features/soft_navigations/aggregate/index.js +33 -23
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +2 -1
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +13 -13
- package/dist/esm/features/soft_navigations/constants.js +4 -1
- package/dist/esm/features/spa/aggregate/index.js +8 -11
- package/dist/esm/features/utils/aggregate-base.js +66 -27
- package/dist/esm/features/utils/event-buffer.js +0 -1
- package/dist/esm/features/utils/event-store-manager.js +103 -0
- package/dist/esm/features/utils/instrument-base.js +1 -10
- package/dist/esm/loaders/api/api-methods.js +1 -1
- package/dist/esm/loaders/api/api.js +2 -1
- package/dist/esm/loaders/features/features.js +15 -9
- package/dist/esm/loaders/micro-agent-base.js +10 -0
- package/dist/esm/loaders/micro-agent.js +1 -0
- package/dist/types/common/aggregate/event-aggregator.d.ts +1 -1
- package/dist/types/common/aggregate/event-aggregator.d.ts.map +1 -1
- 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 +16 -0
- package/dist/types/common/harvest/harvester.d.ts.map +1 -0
- package/dist/types/common/harvest/types.d.ts +8 -45
- package/dist/types/common/harvest/types.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +1 -3
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/constants.d.ts +1 -0
- package/dist/types/features/generic_events/constants.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +0 -3
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts +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 +6 -2
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +12 -15
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +0 -5
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +8 -5
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +1 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +3 -3
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/constants.d.ts +1 -0
- package/dist/types/features/soft_navigations/constants.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +0 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +12 -7
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/event-buffer.d.ts +1 -2
- package/dist/types/features/utils/event-buffer.d.ts.map +1 -1
- package/dist/types/features/utils/event-store-manager.d.ts +43 -0
- package/dist/types/features/utils/event-store-manager.d.ts.map +1 -0
- package/dist/types/features/utils/instrument-base.d.ts +0 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +1 -0
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +15 -12
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/dist/types/loaders/micro-agent-base.d.ts +7 -0
- package/dist/types/loaders/micro-agent-base.d.ts.map +1 -1
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/common/aggregate/event-aggregator.js +1 -1
- package/src/common/config/init.js +9 -10
- package/src/common/config/runtime.js +2 -1
- package/src/common/harvest/__mocks__/harvester.js +6 -0
- package/src/common/harvest/harvester.js +230 -0
- package/src/common/harvest/types.js +5 -21
- package/src/features/ajax/aggregate/index.js +3 -14
- package/src/features/generic_events/aggregate/index.js +20 -17
- package/src/features/generic_events/constants.js +2 -0
- package/src/features/jserrors/aggregate/index.js +4 -11
- package/src/features/logging/aggregate/index.js +4 -12
- package/src/features/metrics/aggregate/index.js +5 -12
- package/src/features/page_view_event/aggregate/index.js +38 -38
- package/src/features/page_view_timing/aggregate/index.js +1 -12
- package/src/features/session_replay/aggregate/index.js +19 -42
- package/src/features/session_replay/instrument/index.js +1 -1
- package/src/features/session_replay/shared/recorder.js +6 -6
- package/src/features/session_trace/aggregate/index.js +8 -25
- package/src/features/session_trace/aggregate/trace/storage.js +5 -2
- package/src/features/soft_navigations/aggregate/index.js +26 -23
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +2 -1
- package/src/features/soft_navigations/aggregate/interaction.js +13 -12
- package/src/features/soft_navigations/constants.js +3 -1
- package/src/features/spa/aggregate/index.js +8 -11
- package/src/features/utils/aggregate-base.js +59 -27
- package/src/features/utils/event-buffer.js +0 -1
- package/src/features/utils/event-store-manager.js +101 -0
- package/src/features/utils/instrument-base.js +2 -8
- package/src/loaders/api/api-methods.js +1 -1
- package/src/loaders/api/api.js +3 -1
- package/src/loaders/features/features.js +16 -9
- package/src/loaders/micro-agent-base.js +10 -0
- package/src/loaders/micro-agent.js +1 -0
- package/dist/cjs/common/harvest/harvest-scheduler.js +0 -168
- package/dist/cjs/common/harvest/harvest.js +0 -295
- package/dist/esm/common/harvest/harvest-scheduler.js +0 -160
- package/dist/esm/common/harvest/harvest.js +0 -286
- package/dist/types/common/harvest/harvest-scheduler.d.ts +0 -50
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +0 -1
- package/dist/types/common/harvest/harvest.d.ts +0 -65
- package/dist/types/common/harvest/harvest.d.ts.map +0 -1
- package/src/common/harvest/__mocks__/harvest.js +0 -13
- package/src/common/harvest/harvest-scheduler.js +0 -166
- package/src/common/harvest/harvest.js +0 -282
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/index.js"],"names":[],"mappings":"AAYA;IACE,2BAAiC;IACjC;;OAkDC;IA/CC,2BAAwC;IACxC,iBAA8B;IAE9B,uDAA0F;IAa1F,yBAA+B;IAC/B,0CAAiC;IACjC,sBAA4B;IA+B9B,qCAUC;IAED,0EAiBC;IAED,2BAiBC;IAED;;;;;;;OAOG;IACH,6BAHW,mBAAmB,OAqB7B;;CA6FF;8BArO6B,4BAA4B;2CAGf,iCAAiC;4BAChD,eAAe"}
|
package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initial-page-load-interaction.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/initial-page-load-interaction.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initial-page-load-interaction.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/initial-page-load-interaction.js"],"names":[],"mappings":"AAQA;IACE,kCAKC;IAED,sBAAqD;IACrD,gCAAyE;IAEzE;;;OAGG;IACH,oCA6BC;CACF;4BApD2B,eAAe"}
|
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
* link https://github.com/newrelic/nr-querypack/blob/main/schemas/bel/7.qpschema
|
|
3
3
|
**/
|
|
4
4
|
export class Interaction extends BelNode {
|
|
5
|
-
constructor(agentIdentifier: any, uiEvent: any, uiEventTimestamp: any, currentRouteKnown: any);
|
|
5
|
+
constructor(agentIdentifier: any, uiEvent: any, uiEventTimestamp: any, currentRouteKnown: any, currentUrl: any);
|
|
6
6
|
id: string;
|
|
7
7
|
initialPageURL: string;
|
|
8
|
-
oldURL: string;
|
|
9
|
-
newURL: string;
|
|
10
8
|
customName: any;
|
|
11
9
|
customAttributes: {};
|
|
12
10
|
customDataByApi: {};
|
|
@@ -27,6 +25,8 @@ export class Interaction extends BelNode {
|
|
|
27
25
|
eventSubscription: Map<string, never[]>;
|
|
28
26
|
forceSave: boolean;
|
|
29
27
|
forceIgnore: boolean;
|
|
28
|
+
newURL: any;
|
|
29
|
+
oldURL: any;
|
|
30
30
|
updateDom(timestamp: any): void;
|
|
31
31
|
updateHistory(timestamp: any, newUrl: any): void;
|
|
32
32
|
seenHistoryAndDomChange(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/interaction.js"],"names":[],"mappings":"AASA;;IAEI;AACJ;
|
|
1
|
+
{"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/interaction.js"],"names":[],"mappings":"AASA;;IAEI;AACJ;IAkBE,gHAaC;IA9BD,WAAmB;IACnB,uBAAgC;IAChC,gBAAU;IACV,qBAAqB;IACrB,oBAAoB;IACpB,eAAS;IACT,aAAO;IACP,cAAQ;IACR,+EAA+E;IAC/E,eAA8B;IAC9B,qBAAgB;IAChB,yBAAoB;IACpB,sBAAoB;IACpB,6BAA2B;IAC3B,cAAW;IACX,uBAAiB;IAIf,gBAAoC;IACpC,aAAsB;IAEtB,cAAiC;IACjC,wCAGE;IACF,mBAAyC;IAAxB,qBAAwB;IAEzC,YAAsE;IAAxD,YAAwD;IAGxE,gCAEC;IAED,iDAGC;IAED,mCAEC;IAED,8BAIC;IAED,kCAaC;IAsBD;;;;;OAKG;IACH,0BAHW,mBAAmB,WAM7B;IAGD,uBAAoB;IACpB,iCAA8B;IAC9B,sBAAmB;IAEnB,gDA4CC;;CACF;wBAzJuB,YAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/soft_navigations/constants.js"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/soft_navigations/constants.js"],"names":[],"mappings":"AAEA,4CAKC;AACD,qCAAqC;AACrC,iDAAiD;AAEjD,kCAAiD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/spa/aggregate/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/spa/aggregate/index.js"],"names":[],"mappings":"AA6BA;IACE,2BAAiC;IACjC,2BAwrBC;IArrBe;;;;;;;;;;;;;;MAeb;IACD,+BAA8C;IAuqBhD,qCAEC;CACF;8BA5sB6B,4BAA4B;2BAJ/B,cAAc"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export class AggregateBase extends FeatureBase {
|
|
2
2
|
agentRef: any;
|
|
3
3
|
events: any;
|
|
4
|
-
|
|
4
|
+
harvestOpts: {};
|
|
5
5
|
/**
|
|
6
6
|
* New handler for waiting for multiple flags. Useful when expecting multiple flags simultaneously (ex. stn vs sr)
|
|
7
7
|
* @param {string[]} flagNames
|
|
@@ -13,21 +13,26 @@ export class AggregateBase extends FeatureBase {
|
|
|
13
13
|
/**
|
|
14
14
|
* Return harvest payload. A "serializer" function can be defined on a derived class to format the payload.
|
|
15
15
|
* @param {Boolean} shouldRetryOnFail - harvester flag to backup payload for retry later if harvest request fails; this should be moved to harvester logic
|
|
16
|
-
* @
|
|
16
|
+
* @param {object|undefined} target - the target app passed onto the event store manager to determine which app's data to return; if none provided, all apps data will be returned
|
|
17
|
+
* @returns {Array} Final payload tagged with their targeting browser app. The value of `payload` can be undefined if there are no pending events for an app. This should be a minimum length of 1.
|
|
17
18
|
*/
|
|
18
|
-
makeHarvestPayload(shouldRetryOnFail
|
|
19
|
-
body: any;
|
|
20
|
-
} | undefined;
|
|
19
|
+
makeHarvestPayload(shouldRetryOnFail: boolean | undefined, target: object | undefined): any[];
|
|
21
20
|
/**
|
|
22
21
|
* Cleanup task after a harvest.
|
|
23
|
-
* @param {
|
|
22
|
+
* @param {object} result - the cbResult object from the harvester's send method
|
|
24
23
|
*/
|
|
25
|
-
postHarvestCleanup(
|
|
24
|
+
postHarvestCleanup(result?: object): void;
|
|
26
25
|
/**
|
|
27
26
|
* Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
|
|
28
27
|
* loader configurations may appear after the loader code is executed.
|
|
29
28
|
*/
|
|
30
29
|
checkConfiguration(existingAgent: any): void;
|
|
30
|
+
/**
|
|
31
|
+
* These are actions related to shared resources that should be initialized once by whichever feature Aggregate subclass loads first.
|
|
32
|
+
* This method should run after checkConfiguration, which may reset the agent's info/runtime object that is used here.
|
|
33
|
+
*/
|
|
34
|
+
doOnceForAllAggregate(agentRef: any): void;
|
|
35
|
+
obfuscator: any;
|
|
31
36
|
}
|
|
32
37
|
import { FeatureBase } from './feature-base';
|
|
33
38
|
//# sourceMappingURL=aggregate-base.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAWA;IAGI,cAAwB;IAcpB,YAAuC;IAM3C,gBAAqB;IAGvB;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAwBlB;IAED,cAGC;IADC,6BAAmB;IAGrB;;;;;OAKG;IACH,mEAHW,MAAM,GAAC,SAAS,SAwB1B;IAED;;;OAGG;IACH,4BAFW,MAAM,QAMhB;IAED;;;OAGG;IACH,6CAsBC;IAED;;;OAGG;IACH,2CASC;IAPC,gBAA6C;CAQhD;4BAvJ2B,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-buffer.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/event-buffer.js"],"names":[],"mappings":"AAGA;IAME;;OAEG;IACH,6BAFW,MAAM,EAIhB;IADC,uBAAoC;IAGtC,mBAEC;IAED,aAEC;IAED,mBAEC;IAED,+CAEC;IAED;;;;OAIG;IACH,WAHW,GAAG,WASb;IAED;;OAEG;IACH,cAGC;IAED
|
|
1
|
+
{"version":3,"file":"event-buffer.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/event-buffer.js"],"names":[],"mappings":"AAGA;IAME;;OAEG;IACH,6BAFW,MAAM,EAIhB;IADC,uBAAoC;IAGtC,mBAEC;IAED,aAEC;IAED,mBAEC;IAED,+CAEC;IAED;;;;OAIG;IACH,WAHW,GAAG,WASb;IAED;;OAEG;IACH,cAGC;IAED;;OAEG;IACH,aAGC;IAED;;OAEG;IACH,kBAGC;IAED;;OAEG;IACH,mBAKC;;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This layer allows multiple browser entity apps, or "target", to each have their own segregated storage instance.
|
|
3
|
+
* The purpose is so the harvester can send data to different apps within the same agent. Each feature should have a manager if it needs this capability.
|
|
4
|
+
*/
|
|
5
|
+
export class EventStoreManager {
|
|
6
|
+
/**
|
|
7
|
+
* @param {object} defaultTarget - should contain licenseKey and appId of the main app from NREUM.info at startup
|
|
8
|
+
* @param {1|2} storageChoice - the type of storage to use in this manager; 'EventBuffer' (1), 'EventAggregator' (2)
|
|
9
|
+
*/
|
|
10
|
+
constructor(defaultTarget: object, storageChoice: 1 | 2);
|
|
11
|
+
mainApp: object;
|
|
12
|
+
StorageClass: typeof EventAggregator | typeof EventBuffer;
|
|
13
|
+
appStorageMap: Map<any, any>;
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} optsIfPresent - exists if called during harvest interval, @see AggregateBase.makeHarvestPayload
|
|
16
|
+
* @param {object} target - specific app's storage to check; if not provided, this method takes into account all apps recorded by this manager
|
|
17
|
+
* @returns {boolean} True if the target's storage is empty, or target does not exist in map (defaults to all storages)
|
|
18
|
+
*/
|
|
19
|
+
isEmpty(optsIfPresent: object, target: object): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} event - the event element to store
|
|
22
|
+
* @param {object} target - the app to store event under; if not provided, this method adds to the main app from NREUM.info
|
|
23
|
+
* @returns {boolean} True if the event was successfully added
|
|
24
|
+
*/
|
|
25
|
+
add(event: string, target: object): boolean;
|
|
26
|
+
/** This is only used by the Metrics feature which has no need to add metric under a different app atm. */
|
|
27
|
+
addMetric(type: any, name: any, params: any, value: any): any;
|
|
28
|
+
/**
|
|
29
|
+
* @param {object} optsIfPresent - exists if called during harvest interval, @see AggregateBase.makeHarvestPayload
|
|
30
|
+
* @param {object} target - specific app to fetch; if not provided, this method fetches from all apps
|
|
31
|
+
* @returns {Array} Objects of `data` labeled with their respective `target` app to be sent to
|
|
32
|
+
*/
|
|
33
|
+
get(optsIfPresent: object, target: object): any[];
|
|
34
|
+
byteSize(target: any): any;
|
|
35
|
+
wouldExceedMaxSize(incomingSize: any, target: any): any;
|
|
36
|
+
save(optsIfPresent: any, target: any): any;
|
|
37
|
+
clear(optsIfPresent: any, target: any): any;
|
|
38
|
+
reloadSave(optsIfPresent: any, target: any): any;
|
|
39
|
+
clearSave(optsIfPresent: any, target: any): any;
|
|
40
|
+
}
|
|
41
|
+
import { EventAggregator } from '../../common/aggregate/event-aggregator';
|
|
42
|
+
import { EventBuffer } from './event-buffer';
|
|
43
|
+
//# sourceMappingURL=event-store-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store-manager.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/event-store-manager.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH;IACE;;;OAGG;IACH,2BAHW,MAAM,iBACN,CAAC,GAAC,CAAC,EAOb;IAJC,gBAA4B;IAC5B,0DAAuE;IACvE,6BAA8B;IAMhC;;;;OAIG;IACH,uBAJW,MAAM,UACN,MAAM,GACJ,OAAO,CAWnB;IAED;;;;OAIG;IACH,WAJW,MAAM,UACN,MAAM,GACJ,OAAO,CAKnB;IAED,0GAA0G;IAC1G,8DAEC;IAED;;;;OAIG;IACH,mBAJW,MAAM,UACN,MAAM,SAUhB;IAED,2BAEC;IAED,wDAEC;IAED,2CAGC;IAED,4CAGC;IAGD,iDAMC;IAED,gDAMC;CACF;gCApG+B,yCAAyC;4BAC7C,gBAAgB"}
|
|
@@ -23,7 +23,6 @@ export class InstrumentBase extends FeatureBase {
|
|
|
23
23
|
/**
|
|
24
24
|
* @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
|
|
25
25
|
* one another if there are inter-features dependencies.
|
|
26
|
-
* TODO: This is only used for the SPA feature component tests and should be refactored out.
|
|
27
26
|
*/
|
|
28
27
|
onAggregateImported: Promise<any>;
|
|
29
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAgBA;;;GAGG;AACH;IACE;;;;;;;OAOG;IACH,wCALW,MAAM,
|
|
1
|
+
{"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAgBA;;;GAGG;AACH;IACE;;;;;;;OAOG;IACH,wCALW,MAAM,8BAqChB;IA9BC,cAAgB;IAEhB,8IAA8I;IAC9I,cADW,WAAW,SAAS,CACF;IAE7B;;;MAGE;IACF,eAHU,OAAO,kBAAkB,EAAE,aAAa,CAGpB;IAE9B;;;MAGE;IACF,kCAAoC;IAiBtC;;;;;;OAMG;IACH,kFAmDC;;CAkBF;4BApI2B,gBAAgB"}
|
|
@@ -9,6 +9,7 @@ export function setAPI(agentIdentifier: any, forceDrain: any, runSoftNavOverSpa?
|
|
|
9
9
|
level?: string | undefined;
|
|
10
10
|
}): void;
|
|
11
11
|
addPageAction: (...args: any[]) => any;
|
|
12
|
+
recordCustomEvent: (...args: any[]) => any;
|
|
12
13
|
setPageViewName(name: any, host: any): any;
|
|
13
14
|
setCustomAttribute(name: any, value: any, persistAttribute?: boolean): any;
|
|
14
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAuBA,2CAiBC;AAID
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAuBA,2CAiBC;AAID;;;;;;;;;;;;;IAmEE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
export const EVENTS: "events";
|
|
2
|
+
export const JSERRORS: "jserrors";
|
|
3
|
+
export const RUM: "rum";
|
|
1
4
|
export namespace FEATURE_NAMES {
|
|
2
|
-
let ajax: string;
|
|
3
|
-
let genericEvents: string;
|
|
4
|
-
|
|
5
|
-
let logging: string;
|
|
6
|
-
let metrics: string;
|
|
7
|
-
let pageAction: string;
|
|
8
|
-
let pageViewEvent: string;
|
|
9
|
-
let pageViewTiming: string;
|
|
10
|
-
let sessionReplay: string;
|
|
11
|
-
let sessionTrace: string;
|
|
12
|
-
let softNav: string;
|
|
13
|
-
let spa: string;
|
|
5
|
+
export let ajax: string;
|
|
6
|
+
export let genericEvents: string;
|
|
7
|
+
export { JSERRORS as jserrors };
|
|
8
|
+
export let logging: string;
|
|
9
|
+
export let metrics: string;
|
|
10
|
+
export let pageAction: string;
|
|
11
|
+
export let pageViewEvent: string;
|
|
12
|
+
export let pageViewTiming: string;
|
|
13
|
+
export let sessionReplay: string;
|
|
14
|
+
export let sessionTrace: string;
|
|
15
|
+
export let softNav: string;
|
|
16
|
+
export let spa: string;
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* The order in which features will be instrumented. This is the traditional order. It's unclear if the order of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/features.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/features.js"],"names":[],"mappings":"AACA,8BAA8B;AAC9B,kCAAkC;AAElC,wBAAwB;;;;;;;;;;;;;;;AAoBxB;;;GAGG;AACH;;EAYC;AAED;;EAYC"}
|
|
@@ -8,6 +8,13 @@ export class MicroAgentBase {
|
|
|
8
8
|
* @param {object} [attributes] JSON object with one or more key/value pairs. For example: {key:"value"}. The key is reported as its own PageAction attribute with the specified values.
|
|
9
9
|
*/
|
|
10
10
|
addPageAction(name: string, attributes?: object | undefined): any;
|
|
11
|
+
/**
|
|
12
|
+
* Records a custom event with a specified eventType and attributes.
|
|
13
|
+
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/recordCustomEvent/}
|
|
14
|
+
* @param {string} eventType The eventType to store the event as.
|
|
15
|
+
* @param {object} [attributes] JSON object with one or more key/value pairs. For example: {key:"value"}.
|
|
16
|
+
*/
|
|
17
|
+
recordCustomEvent(eventType: string, attributes?: object | undefined): any;
|
|
11
18
|
/**
|
|
12
19
|
* Groups page views to help URL structure or to capture the URL's routing information.
|
|
13
20
|
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setpageviewname/}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"micro-agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent-base.js"],"names":[],"mappings":"AAGA;IAGE,sCAEC;IAJD,wBAAe;IAkBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;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;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF"}
|
|
1
|
+
{"version":3,"file":"micro-agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent-base.js"],"names":[],"mappings":"AAGA;IAGE,sCAEC;IAJD,wBAAe;IAkBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;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;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,
|
|
1
|
+
{"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,EAsDjB;IAjDC,aAAkB;IAMlB;;;;OAIG;IACH,iEAmCC;IAKH;;;;;MAOC;CACF;+BAjF8B,oBAAoB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/browser-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.278.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
|
|
6
6
|
"description": "New Relic Browser Agent",
|
|
@@ -228,9 +228,9 @@
|
|
|
228
228
|
"@newrelic/nr-querypack": "https://git@github.com/newrelic/nr-querypack",
|
|
229
229
|
"@wdio/cli": "^8.27.0",
|
|
230
230
|
"@wdio/local-runner": "^8.27.0",
|
|
231
|
-
"@wdio/logger": "^
|
|
231
|
+
"@wdio/logger": "^9.4.4",
|
|
232
232
|
"@wdio/mocha-framework": "^8.27.0",
|
|
233
|
-
"@wdio/spec-reporter": "^
|
|
233
|
+
"@wdio/spec-reporter": "^9.5.0",
|
|
234
234
|
"babel-jest": "^29.7.0",
|
|
235
235
|
"babel-loader": "^9.1.3",
|
|
236
236
|
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
"eslint-plugin-promise": "^6.1.1",
|
|
244
244
|
"eslint-plugin-sonarjs": "^0.23.0",
|
|
245
245
|
"fastify": "^4.25.2",
|
|
246
|
-
"fastify-plugin": "^
|
|
246
|
+
"fastify-plugin": "^5.0.1",
|
|
247
247
|
"form-data": "^4.0.0",
|
|
248
248
|
"fs-extra": "^11.2.0",
|
|
249
249
|
"glob": "^11.0.0",
|
|
@@ -256,7 +256,7 @@
|
|
|
256
256
|
"jest": "^29.7.0",
|
|
257
257
|
"jest-environment-jsdom": "29.7.0",
|
|
258
258
|
"jest-extended": "^4.0.2",
|
|
259
|
-
"jsonpath-plus": "^
|
|
259
|
+
"jsonpath-plus": "^10.0.7",
|
|
260
260
|
"jung": "^2.1.0",
|
|
261
261
|
"node-fetch": "^3.3.2",
|
|
262
262
|
"npm-run-all": "^4.1.5",
|
|
@@ -264,7 +264,7 @@
|
|
|
264
264
|
"terser-webpack-plugin": "^5.3.10",
|
|
265
265
|
"tsd": "^0.30.0",
|
|
266
266
|
"typescript": "^5.3.3",
|
|
267
|
-
"uuid": "^
|
|
267
|
+
"uuid": "^11.0.3",
|
|
268
268
|
"wait-on": "^8.0.0",
|
|
269
269
|
"wdio-lambdatest-service": "^3.0.1",
|
|
270
270
|
"webpack": "^5.89.0",
|
|
@@ -13,7 +13,7 @@ export class EventAggregator {
|
|
|
13
13
|
return aggregatorTypes.every(type => !this.#aggregator.aggregatedData[type]) // no bucket exist for any of the types we're looking for
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
add (type, name, params, newMetrics, customParams) {
|
|
16
|
+
add ([type, name, params, newMetrics, customParams]) {
|
|
17
17
|
// Do we need to track byte size here like EventBuffer?
|
|
18
18
|
this.#aggregator.store(type, name, params, newMetrics, customParams)
|
|
19
19
|
return true
|
|
@@ -39,7 +39,7 @@ const model = () => {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
return {
|
|
42
|
-
ajax: { deny_list: undefined, block_internal: true, enabled: true,
|
|
42
|
+
ajax: { deny_list: undefined, block_internal: true, enabled: true, autoStart: true },
|
|
43
43
|
distributed_tracing: {
|
|
44
44
|
enabled: undefined,
|
|
45
45
|
exclude_newrelic_header: undefined,
|
|
@@ -49,15 +49,15 @@ const model = () => {
|
|
|
49
49
|
},
|
|
50
50
|
get feature_flags () { return hiddenState.feature_flags },
|
|
51
51
|
set feature_flags (val) { hiddenState.feature_flags = val },
|
|
52
|
-
generic_events: { enabled: true,
|
|
53
|
-
harvest: {
|
|
54
|
-
jserrors: { enabled: true,
|
|
55
|
-
logging: { enabled: true,
|
|
52
|
+
generic_events: { enabled: true, autoStart: true },
|
|
53
|
+
harvest: { interval: 30 },
|
|
54
|
+
jserrors: { enabled: true, autoStart: true },
|
|
55
|
+
logging: { enabled: true, autoStart: true, level: LOG_LEVELS.INFO },
|
|
56
56
|
metrics: { enabled: true, autoStart: true },
|
|
57
57
|
obfuscate: undefined,
|
|
58
58
|
page_action: { enabled: true },
|
|
59
59
|
page_view_event: { enabled: true, autoStart: true },
|
|
60
|
-
page_view_timing: { enabled: true,
|
|
60
|
+
page_view_timing: { enabled: true, autoStart: true },
|
|
61
61
|
performance: {
|
|
62
62
|
get capture_marks () { return hiddenState.feature_flags.includes(FEATURE_FLAGS.MARKS) || hiddenState.experimental.marks },
|
|
63
63
|
set capture_marks (val) { hiddenState.experimental.marks = val },
|
|
@@ -85,7 +85,6 @@ const model = () => {
|
|
|
85
85
|
// feature settings
|
|
86
86
|
autoStart: true,
|
|
87
87
|
enabled: false,
|
|
88
|
-
harvestTimeSeconds: 60,
|
|
89
88
|
preload: false, // if true, enables the agent to load rrweb immediately instead of waiting to do so after the window.load event
|
|
90
89
|
sampling_rate: 10, // float from 0 - 100
|
|
91
90
|
error_sampling_rate: 100, // float from 0 - 100
|
|
@@ -123,9 +122,9 @@ const model = () => {
|
|
|
123
122
|
else warn(7, val)
|
|
124
123
|
}
|
|
125
124
|
},
|
|
126
|
-
session_trace: { enabled: true,
|
|
127
|
-
soft_navigations: { enabled: true,
|
|
128
|
-
spa: { enabled: true,
|
|
125
|
+
session_trace: { enabled: true, autoStart: true },
|
|
126
|
+
soft_navigations: { enabled: true, autoStart: true },
|
|
127
|
+
spa: { enabled: true, autoStart: true },
|
|
129
128
|
ssl: undefined,
|
|
130
129
|
user_actions: { enabled: true }
|
|
131
130
|
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { FEATURE_TO_ENDPOINT, JSERRORS, RUM, EVENTS } from '../../loaders/features/features'
|
|
2
|
+
import { VERSION } from '../constants/env'
|
|
3
|
+
import { globalScope, isWorkerScope } from '../constants/runtime'
|
|
4
|
+
import { eventListenerOpts } from '../event-listener/event-listener-opts'
|
|
5
|
+
import { SESSION_EVENTS } from '../session/constants'
|
|
6
|
+
import { now } from '../timing/now'
|
|
7
|
+
import { subscribeToEOL } from '../unload/eol'
|
|
8
|
+
import { cleanURL } from '../url/clean-url'
|
|
9
|
+
import { obj, param } from '../url/encode'
|
|
10
|
+
import { warn } from '../util/console'
|
|
11
|
+
import { stringify } from '../util/stringify'
|
|
12
|
+
import { getSubmitMethod, xhr as xhrMethod, xhrFetch as fetchMethod } from '../util/submit-data'
|
|
13
|
+
|
|
14
|
+
export class Harvester {
|
|
15
|
+
#started = false
|
|
16
|
+
initializedAggregates = []
|
|
17
|
+
|
|
18
|
+
constructor (agentRef) {
|
|
19
|
+
this.agentRef = agentRef
|
|
20
|
+
|
|
21
|
+
subscribeToEOL(() => { // do one last harvest round or check
|
|
22
|
+
this.initializedAggregates.forEach(aggregateInst => { // let all features wrap up things needed to do before ANY harvest in case there's last minute cross-feature data dependencies
|
|
23
|
+
if (typeof aggregateInst.harvestOpts.beforeUnload === 'function') aggregateInst.harvestOpts.beforeUnload()
|
|
24
|
+
})
|
|
25
|
+
this.initializedAggregates.forEach(aggregateInst => this.triggerHarvestFor(aggregateInst, { isFinalHarvest: true }))
|
|
26
|
+
/* This callback should run in bubble phase, so that that CWV api, like "onLCP", is called before the final harvest so that emitted timings are part of last outgoing. */
|
|
27
|
+
}, false)
|
|
28
|
+
|
|
29
|
+
/* Flush all buffered data if session resets and give up retries. This should be synchronous to ensure that the correct `session` value is sent.
|
|
30
|
+
Since session-reset generates a new session ID and the ID is grabbed at send-time, any delays or retries would cause the payload to be sent under the wrong session ID. */
|
|
31
|
+
agentRef.ee.on(SESSION_EVENTS.RESET, () => this.initializedAggregates.forEach(aggregateInst => this.triggerHarvestFor(aggregateInst, { forceNoRetry: true })))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
startTimer (harvestInterval = this.agentRef.init.harvest.interval) {
|
|
35
|
+
if (this.#started) return
|
|
36
|
+
this.#started = true
|
|
37
|
+
|
|
38
|
+
const onHarvestInterval = () => {
|
|
39
|
+
this.initializedAggregates.forEach(aggregateInst => this.triggerHarvestFor(aggregateInst))
|
|
40
|
+
setTimeout(onHarvestInterval, harvestInterval * 1000) // repeat in X seconds
|
|
41
|
+
}
|
|
42
|
+
setTimeout(onHarvestInterval, harvestInterval * 1000)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Given a feature (aggregate), execute a harvest on-demand.
|
|
47
|
+
* @param {object} aggregateInst
|
|
48
|
+
* @param {object} localOpts
|
|
49
|
+
* @returns {boolean} True if 1+ network call was made. Note that this does not mean or guarantee that it was successful (or that all were in the case of more than 1).
|
|
50
|
+
*/
|
|
51
|
+
triggerHarvestFor (aggregateInst, localOpts = {}) {
|
|
52
|
+
if (aggregateInst.blocked) return false
|
|
53
|
+
|
|
54
|
+
const submitMethod = getSubmitMethod(localOpts)
|
|
55
|
+
if (!submitMethod) return false
|
|
56
|
+
|
|
57
|
+
const shouldRetryOnFail = !localOpts.isFinalHarvest && submitMethod === xhrMethod // always retry all features harvests except for final
|
|
58
|
+
let dataToSendArr; let ranSend = false
|
|
59
|
+
if (!localOpts.directSend) { // primarily used by rum call to bypass makeHarvestPayload by providing payload directly
|
|
60
|
+
dataToSendArr = aggregateInst.makeHarvestPayload(shouldRetryOnFail) // be sure the 'this' of makeHarvestPayload is the aggregate w/ access to its harvestOpts
|
|
61
|
+
if (!dataToSendArr) return false // can be undefined if storage is empty or preharvest checks failed
|
|
62
|
+
} else dataToSendArr = [localOpts.directSend]
|
|
63
|
+
|
|
64
|
+
dataToSendArr.forEach(({ targetApp, payload }) => {
|
|
65
|
+
if (!payload) return
|
|
66
|
+
|
|
67
|
+
send(this.agentRef, {
|
|
68
|
+
endpoint: FEATURE_TO_ENDPOINT[aggregateInst.featureName],
|
|
69
|
+
targetApp,
|
|
70
|
+
payload,
|
|
71
|
+
localOpts,
|
|
72
|
+
submitMethod,
|
|
73
|
+
cbFinished,
|
|
74
|
+
raw: aggregateInst.harvestOpts.raw
|
|
75
|
+
})
|
|
76
|
+
ranSend = true
|
|
77
|
+
})
|
|
78
|
+
return ranSend
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
|
|
82
|
+
* @param {Object} result - information regarding the result of the harvest attempt
|
|
83
|
+
*/
|
|
84
|
+
function cbFinished (result) {
|
|
85
|
+
if (localOpts.forceNoRetry) result.retry = false // discard unsent data rather than re-queuing for next harvest attempt
|
|
86
|
+
aggregateInst.postHarvestCleanup(result)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @typedef {import('./types.js').NetworkSendSpec} NetworkSendSpec
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
const warnings = {}
|
|
96
|
+
/**
|
|
97
|
+
* Initiate a harvest call.
|
|
98
|
+
* @param {NetworkSendSpec} param0 Specification for sending data
|
|
99
|
+
* @returns {boolean} True if a network call was made. Note that this does not mean or guarantee that it was successful.
|
|
100
|
+
*/
|
|
101
|
+
function send (agentRef, { endpoint, targetApp, payload, localOpts = {}, submitMethod, cbFinished, raw }) {
|
|
102
|
+
if (!agentRef.info.errorBeacon) return false
|
|
103
|
+
|
|
104
|
+
let { body, qs } = cleanPayload(payload)
|
|
105
|
+
|
|
106
|
+
if (Object.keys(body).length === 0 && !localOpts.sendEmptyBody) { // if there's no body to send, just run onfinish stuff and return
|
|
107
|
+
if (cbFinished) cbFinished({ sent: false, targetApp })
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const protocol = agentRef.init.ssl === false ? 'http' : 'https'
|
|
112
|
+
const perceivedBeacon = agentRef.init.proxy.beacon || agentRef.info.errorBeacon
|
|
113
|
+
const url = raw
|
|
114
|
+
? `${protocol}://${perceivedBeacon}/${endpoint}`
|
|
115
|
+
: `${protocol}://${perceivedBeacon}${endpoint !== RUM ? '/' + endpoint : ''}/1/${targetApp.licenseKey}`
|
|
116
|
+
const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint, targetApp.appId) : ''
|
|
117
|
+
let payloadParams = obj(qs, agentRef.runtime.maxBytes)
|
|
118
|
+
if (baseParams === '' && payloadParams.startsWith('&')) {
|
|
119
|
+
payloadParams = payloadParams.substring(1)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const fullUrl = `${url}?${baseParams}${payloadParams}`
|
|
123
|
+
const gzip = !!qs?.attributes?.includes('gzip')
|
|
124
|
+
if (!gzip) {
|
|
125
|
+
if (endpoint !== EVENTS) body = stringify(body) // all features going to 'events' endpoint should already be serialized & stringified
|
|
126
|
+
// Warn--once per endpoint--if the agent tries to send large payloads
|
|
127
|
+
if (body.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) warn(28, endpoint)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If body is null, undefined, or an empty object or array after stringifying, send an empty string instead.
|
|
131
|
+
if (!body || body.length === 0 || body === '{}' || body === '[]') body = ''
|
|
132
|
+
|
|
133
|
+
const headers = [{ key: 'content-type', value: 'text/plain' }]
|
|
134
|
+
|
|
135
|
+
/* Since workers don't support sendBeacon right now, they can only use XHR method.
|
|
136
|
+
Because they still do permit synch XHR, the idea is that at final harvest time (worker is closing),
|
|
137
|
+
we just make a BLOCKING request--trivial impact--with the remaining data as a temp fill-in for sendBeacon.
|
|
138
|
+
Following the removal of img-element method. */
|
|
139
|
+
let result = submitMethod({ url: fullUrl, body, sync: localOpts.isFinalHarvest && isWorkerScope, headers })
|
|
140
|
+
|
|
141
|
+
if (!localOpts.isFinalHarvest && cbFinished) { // final harvests don't hold onto buffer data (shouldRetryOnFail is false), so cleanup isn't needed
|
|
142
|
+
if (submitMethod === xhrMethod) {
|
|
143
|
+
result.addEventListener('loadend', function () {
|
|
144
|
+
// `this` here in block refers to the XHR object in this scope, do not change the anon function to an arrow function
|
|
145
|
+
// status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
|
|
146
|
+
const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), xhr: this, fullUrl, targetApp }
|
|
147
|
+
if (localOpts.needResponse) cbResult.responseText = this.responseText
|
|
148
|
+
cbFinished(cbResult)
|
|
149
|
+
}, eventListenerOpts(false))
|
|
150
|
+
} else if (submitMethod === fetchMethod) {
|
|
151
|
+
result.then(async function (response) {
|
|
152
|
+
const status = response.status
|
|
153
|
+
const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response, targetApp }
|
|
154
|
+
if (localOpts.needResponse) cbResult.responseText = await response.text()
|
|
155
|
+
cbFinished(cbResult)
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return true
|
|
160
|
+
|
|
161
|
+
function shouldRetry (status) {
|
|
162
|
+
switch (status) {
|
|
163
|
+
case 429:
|
|
164
|
+
case 408:
|
|
165
|
+
case 500:
|
|
166
|
+
case 503:
|
|
167
|
+
return true
|
|
168
|
+
default:
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Cleans and returns a payload object containing a body and qs
|
|
176
|
+
* object with key/value pairs. KV pairs where the value is null,
|
|
177
|
+
* undefined, or an empty string are removed to save on transmission
|
|
178
|
+
* size.
|
|
179
|
+
* @param {HarvestPayload} payload Payload to be sent to the endpoint.
|
|
180
|
+
* @returns {HarvestPayload} Cleaned payload payload to be sent to the endpoint.
|
|
181
|
+
*/
|
|
182
|
+
function cleanPayload (payload = {}) {
|
|
183
|
+
const clean = (input) => {
|
|
184
|
+
if ((typeof Uint8Array !== 'undefined' && input instanceof Uint8Array) || Array.isArray(input)) return input
|
|
185
|
+
if (typeof input === 'string') return input.length > 0 ? input : null
|
|
186
|
+
return Object.entries(input || {}).reduce((accumulator, [key, value]) => {
|
|
187
|
+
if ((typeof value === 'number') ||
|
|
188
|
+
(typeof value === 'string' && value.length > 0) ||
|
|
189
|
+
(typeof value === 'object' && Object.keys(value || {}).length > 0)
|
|
190
|
+
) {
|
|
191
|
+
accumulator[key] = value
|
|
192
|
+
}
|
|
193
|
+
return accumulator
|
|
194
|
+
}, {})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
body: clean(payload.body),
|
|
199
|
+
qs: clean(payload.qs)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// The stuff that gets sent every time.
|
|
204
|
+
function baseQueryString (agentRef, qs, endpoint, applicationID) {
|
|
205
|
+
const ref = agentRef.runtime.obfuscator.obfuscateString(cleanURL('' + globalScope.location))
|
|
206
|
+
const hr = agentRef.runtime.session?.state.sessionReplayMode === 1 && endpoint !== JSERRORS
|
|
207
|
+
|
|
208
|
+
const qps = [
|
|
209
|
+
'a=' + applicationID,
|
|
210
|
+
param('sa', (agentRef.info.sa ? '' + agentRef.info.sa : '')),
|
|
211
|
+
param('v', VERSION),
|
|
212
|
+
transactionNameParam(),
|
|
213
|
+
param('ct', agentRef.runtime.customTransaction),
|
|
214
|
+
'&rst=' + now(),
|
|
215
|
+
'&ck=0', // ck param DEPRECATED - still expected by backend
|
|
216
|
+
'&s=' + (agentRef.runtime.session?.state.value || '0'), // the 0 id encaps all untrackable and default traffic
|
|
217
|
+
param('ref', ref),
|
|
218
|
+
param('ptid', (agentRef.runtime.ptid ? '' + agentRef.runtime.ptid : ''))
|
|
219
|
+
]
|
|
220
|
+
if (hr) qps.push(param('hr', '1', qs))
|
|
221
|
+
return qps.join('')
|
|
222
|
+
|
|
223
|
+
// Constructs the transaction name param for the beacon URL.
|
|
224
|
+
// Prefers the obfuscated transaction name over the plain text.
|
|
225
|
+
// Falls back to making up a name.
|
|
226
|
+
function transactionNameParam () {
|
|
227
|
+
if (agentRef.info.transactionName) return param('to', agentRef.info.transactionName)
|
|
228
|
+
return param('t', agentRef.info.tNamePlain || 'Unnamed Transaction')
|
|
229
|
+
}
|
|
230
|
+
}
|