@newrelic/browser-agent 1.237.0 → 1.238.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/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/deny-list/deny-list.js +1 -1
- package/dist/cjs/common/event-emitter/contextual-ee.js +18 -26
- package/dist/cjs/common/event-emitter/event-context.js +12 -0
- package/dist/cjs/common/harvest/harvest.js +4 -4
- package/dist/cjs/common/ids/bundle-id.js +19 -0
- package/dist/cjs/common/wrap/wrap-events.js +3 -2
- package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
- package/dist/cjs/common/wrap/wrap-function.js +15 -46
- package/dist/cjs/common/wrap/wrap-mutation.js +1 -2
- package/dist/cjs/common/wrap/wrap-promise.js +2 -3
- package/dist/cjs/common/wrap/wrap-xhr.js +23 -27
- package/dist/cjs/features/ajax/instrument/distributed-tracing.js +0 -4
- package/dist/cjs/features/ajax/instrument/index.js +19 -9
- package/dist/cjs/features/metrics/aggregate/index.js +8 -0
- package/dist/cjs/features/session_replay/aggregate/index.js +2 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +14 -8
- package/dist/cjs/features/spa/aggregate/index.js +1 -1
- package/dist/cjs/loaders/agent-base.js +12 -0
- package/dist/cjs/loaders/api/api.js +14 -1
- package/dist/cjs/loaders/api/interaction-types.js +11 -4
- package/dist/cjs/loaders/configure/configure.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/deny-list/deny-list.js +1 -1
- package/dist/esm/common/event-emitter/contextual-ee.js +16 -23
- package/dist/esm/common/event-emitter/event-context.js +5 -0
- package/dist/esm/common/harvest/harvest.js +4 -4
- package/dist/esm/common/ids/bundle-id.js +13 -0
- package/dist/esm/common/wrap/wrap-events.js +4 -3
- package/dist/esm/common/wrap/wrap-fetch.js +2 -4
- package/dist/esm/common/wrap/wrap-function.js +15 -44
- package/dist/esm/common/wrap/wrap-mutation.js +2 -3
- package/dist/esm/common/wrap/wrap-promise.js +3 -4
- package/dist/esm/common/wrap/wrap-xhr.js +23 -27
- package/dist/esm/features/ajax/instrument/distributed-tracing.js +0 -4
- package/dist/esm/features/ajax/instrument/index.js +20 -10
- package/dist/esm/features/metrics/aggregate/index.js +8 -0
- package/dist/esm/features/session_replay/aggregate/index.js +2 -0
- package/dist/esm/features/session_trace/aggregate/index.js +14 -8
- package/dist/esm/features/spa/aggregate/index.js +1 -1
- package/dist/esm/loaders/agent-base.js +12 -0
- package/dist/esm/loaders/api/api.js +14 -1
- package/dist/esm/loaders/api/interaction-types.js +11 -4
- package/dist/esm/loaders/configure/configure.js +3 -2
- package/dist/types/common/event-emitter/contextual-ee.d.ts +22 -2
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/event-emitter/event-context.d.ts +5 -0
- package/dist/types/common/event-emitter/event-context.d.ts.map +1 -0
- package/dist/types/common/event-emitter/register-handler.d.ts +1 -1
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/ids/bundle-id.d.ts +5 -0
- package/dist/types/common/ids/bundle-id.d.ts.map +1 -0
- package/dist/types/common/session/session-entity.d.ts +6 -6
- package/dist/types/common/window/nreum.d.ts +2 -2
- package/dist/types/common/wrap/wrap-events.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-function.d.ts +1 -19
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-mutation.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/distributed-tracing.d.ts +1 -1
- package/dist/types/features/ajax/instrument/distributed-tracing.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/endpoint-map.d.ts +5 -5
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +5 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +9 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +6 -0
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/api/interaction-types.d.ts +18 -7
- package/dist/types/loaders/api/interaction-types.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts +1 -0
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +9 -9
- package/dist/types/loaders/micro-agent.d.ts +1 -1
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +22 -27
- package/src/common/deny-list/deny-list.js +1 -1
- package/src/common/deny-list/deny-list.test.js +103 -30
- package/src/common/event-emitter/{contextual-ee.test.js → contextual-ee.component-test.js} +15 -32
- package/src/common/event-emitter/contextual-ee.js +20 -31
- package/src/common/event-emitter/event-context.js +5 -0
- package/src/common/harvest/harvest.js +4 -4
- package/src/common/harvest/harvest.test.js +1 -1
- package/src/common/ids/__mocks__/bundle-id.js +2 -0
- package/src/common/ids/__mocks__/unique-id.js +17 -0
- package/src/common/ids/bundle-id.js +13 -0
- package/src/common/url/__mocks__/parse-url.js +15 -0
- package/src/common/util/__mocks__/get-or-set.js +5 -0
- package/src/common/window/__mocks__/nreum.js +10 -0
- package/src/common/wrap/wrap-events.js +4 -3
- package/src/common/wrap/wrap-fetch.js +2 -4
- package/src/common/wrap/wrap-function.js +16 -44
- package/src/common/wrap/wrap-mutation.js +2 -3
- package/src/common/wrap/{wrap-promise.test.js → wrap-promise.component-test.js} +2 -32
- package/src/common/wrap/wrap-promise.js +3 -4
- package/src/common/wrap/wrap-xhr.js +24 -28
- package/src/features/ajax/instrument/distributed-tracing.js +0 -4
- package/src/features/ajax/instrument/distributed-tracing.test.js +375 -0
- package/src/features/ajax/instrument/index.js +22 -10
- package/src/features/metrics/aggregate/index.js +8 -0
- package/src/features/session_replay/aggregate/index.js +2 -0
- package/src/features/session_trace/aggregate/index.js +16 -7
- package/src/features/spa/aggregate/index.js +1 -1
- package/src/loaders/agent-base.js +12 -0
- package/src/loaders/api/api.component-test.js +45 -0
- package/src/loaders/api/api.js +14 -1
- package/src/loaders/api/interaction-types.js +11 -4
- package/src/loaders/configure/configure.js +11 -2
- /package/src/common/url/{encode.component-test.js → encode.test.js} +0 -0
- /package/src/common/url/{protocol.component-test.js → protocol.test.js} +0 -0
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/browser-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.238.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "New Relic Browser Agent",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"homepage": "https://docs.newrelic.com/docs/browser/browser-monitoring",
|
|
9
9
|
"main": "./dist/cjs/index.js",
|
|
@@ -92,35 +92,30 @@
|
|
|
92
92
|
"node": ">=12.17.0 < 13.0.0 || >=13.7.0"
|
|
93
93
|
},
|
|
94
94
|
"scripts": {
|
|
95
|
-
"wdio": "node --max-old-space-size=8192 tools/wdio/bin/cli.js",
|
|
96
95
|
"start": "npm-run-all --parallel cdn:watch test-server",
|
|
97
|
-
"
|
|
98
|
-
"
|
|
96
|
+
"lint": "eslint -c .eslintrc.js --ext .js,.cjs,.mjs .",
|
|
97
|
+
"lint:fix": "npm run lint -- --fix",
|
|
98
|
+
"test": "jest",
|
|
99
|
+
"test:unit": "jest --selectProjects unit",
|
|
100
|
+
"test:component": "jest --selectProjects component",
|
|
101
|
+
"test:types": "tsd -f ./tests/dts/**/*.ts",
|
|
102
|
+
"wdio": "node --max-old-space-size=8192 tools/wdio/bin/cli.js",
|
|
103
|
+
"jil": "tools/jil/bin/cli.js",
|
|
99
104
|
"build:all": "npm run cdn:build:local && npm run build:npm && npm run tools:test-builds",
|
|
100
105
|
"build:npm": "npm run npm:build:esm && npm run npm:build:cjs && npm run npm:build:types && npm run npm:pack",
|
|
101
106
|
"build:browser-tests": "npm --prefix ./tools/test-builds/browser-tests run build",
|
|
102
|
-
"
|
|
103
|
-
"lint:fix": "npm run lint -- --fix",
|
|
104
|
-
"test-jil": "tools/jil/bin/cli.js",
|
|
105
|
-
"ci-build": "npm ci --cache ./.npm",
|
|
106
|
-
"build-tar": "npm run ci-build && tar czf ./build/browser-agent.tar.gz --exclude=.git --exclude=.npm --exclude=build/browser-agent.tar.gz .",
|
|
107
|
-
"watch": "jung -D '\\.npm|.git|node_modules|build|tools|tests' --run -- npm run build:all",
|
|
107
|
+
"watch:browser-tests": "jung -r ./src -F '.*\\.test\\.js' --run -- npm run build:browser-tests",
|
|
108
108
|
"cdn:build": "npm run cdn:build:prod",
|
|
109
|
-
"cdn:build:
|
|
110
|
-
"cdn:build:
|
|
111
|
-
"
|
|
112
|
-
"cdn:build:dev": "npm run cdn:
|
|
113
|
-
"cdn:build:
|
|
114
|
-
"cdn:
|
|
115
|
-
"
|
|
116
|
-
"cdn:build:experiment": "npm run cdn:fresh-build && PUBLISH=EXPERIMENT npm run cdn:webpack && npm run cdn:cleanup",
|
|
117
|
-
"cdn:cleanup": "node ./tools/scripts/post-build-cleanup",
|
|
118
|
-
"cdn:clone": "node ./tools/scripts/clone",
|
|
119
|
-
"cdn:fresh-build": "rm -rf ./build",
|
|
109
|
+
"cdn:build:local": "npm run cdn:webpack",
|
|
110
|
+
"cdn:build:prod": "npm run cdn:webpack -- --env mode=prod",
|
|
111
|
+
"postcdn:build:prod": "npm run cdn:clone",
|
|
112
|
+
"cdn:build:dev": "npm run cdn:webpack -- --env mode=dev",
|
|
113
|
+
"cdn:build:experiment": "npm run cdn:webpack -- --env mode=experiment",
|
|
114
|
+
"cdn:webpack": "npx webpack --progress --config ./tools/webpack/index.mjs",
|
|
115
|
+
"postcdn:webpack": "npm run cdn:cleanup",
|
|
120
116
|
"cdn:watch": "jung -r ./src -F '.*\\.test\\.js' --run -- npm run cdn:build:local",
|
|
121
|
-
"cdn:
|
|
122
|
-
"cdn:
|
|
123
|
-
"packages:bundle": "webpack -c tools/jil/webpack.modular.js",
|
|
117
|
+
"cdn:cleanup": "node ./tools/webpack/scripts/cleanup.mjs",
|
|
118
|
+
"cdn:clone": "node ./tools/webpack/scripts/clone.mjs",
|
|
124
119
|
"test-server": "node ./tools/wdio/bin/server",
|
|
125
120
|
"sauce:connect": "node ./tools/saucelabs/bin.mjs",
|
|
126
121
|
"sauce:get-browsers": "node ./tools/browsers-lists/sauce-browsers.mjs",
|
|
@@ -130,8 +125,7 @@
|
|
|
130
125
|
"npm:build:esm": "npx babel --env-name npm-esm --out-dir dist/esm --out-file-extension .js ./src",
|
|
131
126
|
"npm:build:cjs": "npx babel --env-name npm-cjs --out-dir dist/cjs --out-file-extension .js ./src",
|
|
132
127
|
"npm:build:types": "npx tsc -b",
|
|
133
|
-
"npm:pack": "mkdir -p temp && export PKG_NAME=$(npm pack --pack-destination temp) && echo ./temp/$PKG_NAME"
|
|
134
|
-
"watch:browser-tests": "jung -r ./src -F '.*\\.test\\.js' --run -- npm run build:browser-tests"
|
|
128
|
+
"npm:pack": "mkdir -p temp && export PKG_NAME=$(npm pack --pack-destination temp) && echo ./temp/$PKG_NAME"
|
|
135
129
|
},
|
|
136
130
|
"config": {
|
|
137
131
|
"unsafe-perm": true
|
|
@@ -228,6 +222,7 @@
|
|
|
228
222
|
"tape": "^4.8.0",
|
|
229
223
|
"through": "^2.3.8",
|
|
230
224
|
"through2": "^2.0.1",
|
|
225
|
+
"tsd": "^0.28.1",
|
|
231
226
|
"typescript": "^5.0.3",
|
|
232
227
|
"uuid": "^9.0.0",
|
|
233
228
|
"wait-on": "^7.0.1",
|
|
@@ -1,31 +1,104 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
jest.enableAutomock()
|
|
2
|
+
jest.unmock('./deny-list')
|
|
3
|
+
|
|
4
|
+
let denyListModule
|
|
5
|
+
|
|
6
|
+
beforeEach(async () => {
|
|
7
|
+
denyListModule = await import('./deny-list')
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
jest.resetModules()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('domain-only blocks all subdomains and all paths', () => {
|
|
15
|
+
denyListModule.setDenyList(['foo.com'])
|
|
16
|
+
|
|
17
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/' })).toBeFalsy()
|
|
18
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a' })).toBeFalsy()
|
|
19
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a/b' })).toBeFalsy()
|
|
20
|
+
|
|
21
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'www.foo.com', pathname: '/' })).toBeFalsy()
|
|
22
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.b.foo.com', pathname: '/' })).toBeFalsy()
|
|
23
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.b.foo.com', pathname: '/c/d' })).toBeFalsy()
|
|
24
|
+
|
|
25
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'oo.com', pathname: '/' })).toBeTruthy()
|
|
26
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.com', pathname: '/' })).toBeTruthy()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('subdomain blocks further subdomains, but not parent domain', () => {
|
|
30
|
+
denyListModule.setDenyList(['bar.foo.com'])
|
|
31
|
+
|
|
32
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.foo.com', pathname: '/' })).toBeFalsy()
|
|
33
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.foo.com', pathname: '/a' })).toBeFalsy()
|
|
34
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.foo.com', pathname: '/a/b' })).toBeFalsy()
|
|
35
|
+
|
|
36
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.bar.foo.com', pathname: '/' })).toBeFalsy()
|
|
37
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.bar.foo.com', pathname: '/a' })).toBeFalsy()
|
|
38
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.bar.foo.com', pathname: '/a/b' })).toBeFalsy()
|
|
39
|
+
|
|
40
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/' })).toBeTruthy()
|
|
41
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a' })).toBeTruthy()
|
|
42
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a/b' })).toBeTruthy()
|
|
43
|
+
|
|
44
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'oo.com', pathname: '/' })).toBeTruthy()
|
|
45
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.com', pathname: '/' })).toBeTruthy()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('* blocks all domains', () => {
|
|
49
|
+
denyListModule.setDenyList(['*'])
|
|
50
|
+
|
|
51
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/' })).toBeFalsy()
|
|
52
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'www.foo.com', pathname: '/' })).toBeFalsy()
|
|
53
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.com', pathname: '/' })).toBeFalsy()
|
|
54
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'www.bar.com', pathname: '/' })).toBeFalsy()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('respects path', () => {
|
|
58
|
+
denyListModule.setDenyList(['bam.nr-data.net/somepath'])
|
|
59
|
+
|
|
60
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', pathname: '/somepath' })).toBeFalsy()
|
|
61
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', port: '7890', protocol: 'https', host: 'bam.nr-data.net:7890', pathname: '/somepath' })).toBeFalsy()
|
|
62
|
+
|
|
63
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.com', pathname: '' })).toBeTruthy()
|
|
64
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.com', pathname: '/someotherpath' })).toBeTruthy()
|
|
65
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.com', pathname: '/some/otherpath' })).toBeTruthy()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('ignores port', () => {
|
|
69
|
+
denyListModule.setDenyList(['bam.nr-data.net:1234'])
|
|
70
|
+
|
|
71
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', pathname: '', port: '4321' })).toBeFalsy()
|
|
72
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', port: '7890', protocol: 'http', host: 'bam.nr-data.net:7890', pathname: '/somepath' })).toBeFalsy()
|
|
73
|
+
|
|
74
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.com', pathname: '' })).toBeTruthy()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('ignores protocol', () => {
|
|
78
|
+
denyListModule.setDenyList(['http://bam.nr-data.net'])
|
|
79
|
+
|
|
80
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', pathname: '', protocol: 'https' })).toBeFalsy()
|
|
81
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.net', port: '7890', protocol: 'https', host: 'bam.nr-data.net:7890', pathname: '/somepath' })).toBeFalsy()
|
|
82
|
+
|
|
83
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bam.nr-data.com', pathname: '', protocol: 'http' })).toBeTruthy()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test.each([
|
|
87
|
+
null,
|
|
88
|
+
undefined,
|
|
89
|
+
'!@$%^*',
|
|
90
|
+
'https://example.com/http://foo.bar/'
|
|
91
|
+
])('ignores invalid deny list value %s', (denyListValue) => {
|
|
92
|
+
denyListModule.setDenyList([denyListValue])
|
|
93
|
+
|
|
94
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/' })).toBeTruthy()
|
|
95
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a' })).toBeTruthy()
|
|
96
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'foo.com', pathname: '/a/b' })).toBeTruthy()
|
|
97
|
+
|
|
98
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'www.foo.com', pathname: '/' })).toBeTruthy()
|
|
99
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.b.foo.com', pathname: '/' })).toBeTruthy()
|
|
100
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'a.b.foo.com', pathname: '/c/d' })).toBeTruthy()
|
|
101
|
+
|
|
102
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'oo.com', pathname: '/' })).toBeTruthy()
|
|
103
|
+
expect(denyListModule.shouldCollectEvent({ hostname: 'bar.com', pathname: '/' })).toBeTruthy()
|
|
31
104
|
})
|
|
@@ -24,19 +24,18 @@ afterEach(() => {
|
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
describe('global event-emitter', () => {
|
|
27
|
-
test('it
|
|
28
|
-
const mockEE = {}
|
|
29
|
-
mockNREUM.ee = mockEE
|
|
30
|
-
|
|
27
|
+
test('it sets the global event-emitter on window.NREUM when it does not already exist', async () => {
|
|
31
28
|
const { ee } = await import('./contextual-ee')
|
|
32
29
|
|
|
33
|
-
expect(ee).toEqual(
|
|
30
|
+
expect(ee).toEqual(mockNREUM.ee)
|
|
34
31
|
})
|
|
35
32
|
|
|
36
|
-
test('it
|
|
33
|
+
test('it does not set the global event-emitter on window.NREUM when it already exists', async () => {
|
|
34
|
+
mockNREUM.ee = {}
|
|
35
|
+
|
|
37
36
|
const { ee } = await import('./contextual-ee')
|
|
38
37
|
|
|
39
|
-
expect(ee).toEqual(mockNREUM.ee)
|
|
38
|
+
expect(ee).not.toEqual(mockNREUM.ee)
|
|
40
39
|
})
|
|
41
40
|
})
|
|
42
41
|
|
|
@@ -79,7 +78,9 @@ describe('event-emitter context', () => {
|
|
|
79
78
|
|
|
80
79
|
const result = ee.context()
|
|
81
80
|
|
|
82
|
-
expect(result).toEqual({
|
|
81
|
+
expect(result).toEqual(expect.objectContaining({
|
|
82
|
+
contextId: expect.stringContaining('nr@context:')
|
|
83
|
+
}))
|
|
83
84
|
})
|
|
84
85
|
|
|
85
86
|
test('it returns the same context', async () => {
|
|
@@ -87,7 +88,7 @@ describe('event-emitter context', () => {
|
|
|
87
88
|
|
|
88
89
|
const result = ee.context()
|
|
89
90
|
|
|
90
|
-
expect(result).
|
|
91
|
+
expect(result).toBe(ee.context(result))
|
|
91
92
|
})
|
|
92
93
|
|
|
93
94
|
test('it adds the context to the provided object', async () => {
|
|
@@ -95,8 +96,9 @@ describe('event-emitter context', () => {
|
|
|
95
96
|
|
|
96
97
|
const obj = {}
|
|
97
98
|
const result = ee.context(obj)
|
|
99
|
+
const ctxKey = Object.getOwnPropertyNames(obj).find(k => k.startsWith('nr@context'))
|
|
98
100
|
|
|
99
|
-
expect(result).
|
|
101
|
+
expect(result).toBe(obj[ctxKey])
|
|
100
102
|
})
|
|
101
103
|
})
|
|
102
104
|
|
|
@@ -281,30 +283,11 @@ describe('event-emitter emit', () => {
|
|
|
281
283
|
scopeEE,
|
|
282
284
|
eventType,
|
|
283
285
|
eventArgs,
|
|
284
|
-
{
|
|
286
|
+
expect.objectContaining({
|
|
287
|
+
contextId: expect.stringContaining('nr@context:')
|
|
288
|
+
})
|
|
285
289
|
])
|
|
286
290
|
]))
|
|
287
291
|
expect(ee.backlog.feature).toEqual(scopeEE.backlog.feature)
|
|
288
292
|
})
|
|
289
293
|
})
|
|
290
|
-
|
|
291
|
-
describe('getOrSetContext', () => {
|
|
292
|
-
test('it returns a new context', async () => {
|
|
293
|
-
const { getOrSetContext } = await import('./contextual-ee')
|
|
294
|
-
|
|
295
|
-
const obj = {}
|
|
296
|
-
const result = getOrSetContext(obj)
|
|
297
|
-
|
|
298
|
-
expect(result).toEqual({})
|
|
299
|
-
expect(result).toEqual(obj['nr@context'])
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
test('it returns the same context', async () => {
|
|
303
|
-
const { getOrSetContext } = await import('./contextual-ee')
|
|
304
|
-
|
|
305
|
-
const obj = {}
|
|
306
|
-
const result = getOrSetContext(obj)
|
|
307
|
-
|
|
308
|
-
expect(getOrSetContext(obj)).toEqual(result)
|
|
309
|
-
})
|
|
310
|
-
})
|
|
@@ -5,25 +5,22 @@
|
|
|
5
5
|
|
|
6
6
|
import { gosNREUM } from '../window/nreum'
|
|
7
7
|
import { getOrSet } from '../util/get-or-set'
|
|
8
|
-
import { mapOwn } from '../util/map-own'
|
|
9
8
|
import { getRuntime } from '../config/config'
|
|
9
|
+
import { EventContext } from './event-context'
|
|
10
|
+
import { bundleId } from '../ids/bundle-id'
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
// create a unique id to store event context data for the current agent bundle
|
|
13
|
+
const contextId = `nr@context:${bundleId}`
|
|
13
14
|
// create global emitter instance that can be shared among bundles
|
|
14
|
-
|
|
15
|
-
var globalInstance
|
|
15
|
+
const globalInstance = ee(undefined, 'globalEE')
|
|
16
16
|
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
globalInstance = ee(undefined, 'globalEE')
|
|
17
|
+
// Only override the exposed event emitter if one has not already been exposed
|
|
18
|
+
const nr = gosNREUM()
|
|
19
|
+
if (!nr.ee) {
|
|
21
20
|
nr.ee = globalInstance
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
export { globalInstance as ee }
|
|
25
|
-
|
|
26
|
-
function EventContext () { }
|
|
23
|
+
export { globalInstance as ee, contextId }
|
|
27
24
|
|
|
28
25
|
function ee (old, debugId) {
|
|
29
26
|
var handlers = {}
|
|
@@ -65,9 +62,9 @@ function ee (old, debugId) {
|
|
|
65
62
|
if (contextOrStore && contextOrStore instanceof EventContext) {
|
|
66
63
|
return contextOrStore
|
|
67
64
|
} else if (contextOrStore) {
|
|
68
|
-
return getOrSet(contextOrStore,
|
|
65
|
+
return getOrSet(contextOrStore, contextId, () => new EventContext(contextId))
|
|
69
66
|
} else {
|
|
70
|
-
return
|
|
67
|
+
return new EventContext(contextId)
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
|
|
@@ -119,17 +116,18 @@ function ee (old, debugId) {
|
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
function bufferEventsByGroup (types, group) {
|
|
122
|
-
|
|
119
|
+
const eventBuffer = getBuffer()
|
|
120
|
+
group = group || 'feature'
|
|
123
121
|
|
|
124
122
|
// do not buffer events if agent has been aborted
|
|
125
123
|
if (emitter.aborted) return
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
Object.entries(types || {})
|
|
125
|
+
.forEach(([_, type]) => {
|
|
126
|
+
bufferGroupMap[type] = group
|
|
127
|
+
if (!(group in eventBuffer)) {
|
|
128
|
+
eventBuffer[group] = []
|
|
129
|
+
}
|
|
130
|
+
})
|
|
133
131
|
}
|
|
134
132
|
|
|
135
133
|
function isBuffering (type) {
|
|
@@ -144,15 +142,6 @@ function ee (old, debugId) {
|
|
|
144
142
|
}
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
// get context object from store object, or create if does not exist
|
|
148
|
-
export function getOrSetContext (obj) {
|
|
149
|
-
return getOrSet(obj, ctxId, getNewContext)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function getNewContext () {
|
|
153
|
-
return new EventContext()
|
|
154
|
-
}
|
|
155
|
-
|
|
156
145
|
function abort () {
|
|
157
146
|
globalInstance.aborted = true
|
|
158
147
|
globalInstance.backlog = {}
|
|
@@ -47,7 +47,8 @@ export class Harvest extends SharedContext {
|
|
|
47
47
|
sendX (spec = {}) {
|
|
48
48
|
const submitMethod = submitData.getSubmitMethod({ isFinalHarvest: spec.opts?.unload })
|
|
49
49
|
const options = {
|
|
50
|
-
retry: !spec.opts?.unload && submitMethod === submitData.xhr
|
|
50
|
+
retry: !spec.opts?.unload && submitMethod === submitData.xhr,
|
|
51
|
+
isFinalHarvest: spec.opts?.unload === true
|
|
51
52
|
}
|
|
52
53
|
const payload = this.createPayload(spec.endpoint, options)
|
|
53
54
|
const caller = this.obfuscator.shouldObfuscate() ? this.obfuscateAndSend.bind(this) : this._send.bind(this)
|
|
@@ -230,9 +231,8 @@ export class Harvest extends SharedContext {
|
|
|
230
231
|
*/
|
|
231
232
|
cleanPayload (payload = {}) {
|
|
232
233
|
const clean = (input) => {
|
|
233
|
-
if ((typeof Uint8Array !== 'undefined' && input instanceof Uint8Array) ||
|
|
234
|
-
|
|
235
|
-
}
|
|
234
|
+
if ((typeof Uint8Array !== 'undefined' && input instanceof Uint8Array) || Array.isArray(input)) return input
|
|
235
|
+
if (typeof input === 'string') return input.length > 0 ? input : null
|
|
236
236
|
return Object.entries(input || {})
|
|
237
237
|
.reduce((accumulator, [key, value]) => {
|
|
238
238
|
if ((typeof value === 'number') ||
|
|
@@ -53,7 +53,7 @@ describe('sendX', () => {
|
|
|
53
53
|
|
|
54
54
|
harvestInstance.sendX(spec)
|
|
55
55
|
|
|
56
|
-
expect(harvestInstance.createPayload).toHaveBeenCalledWith(spec.endpoint, { retry: true })
|
|
56
|
+
expect(harvestInstance.createPayload).toHaveBeenCalledWith(spec.endpoint, { retry: true, isFinalHarvest: false })
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
test('should not use obfuscateAndSend', async () => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { faker } from '@faker-js/faker'
|
|
2
|
+
|
|
3
|
+
export function generateUuid () {
|
|
4
|
+
return faker.datatype.uuid()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function generateRandomHexString (length) {
|
|
8
|
+
return faker.datatype.hexadecimal({ length, prefix: '' })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function generateSpanId () {
|
|
12
|
+
return generateRandomHexString(16)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function generateTraceId () {
|
|
16
|
+
return generateRandomHexString(32)
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Contains a unique identifier for the running agent bundle
|
|
3
|
+
* when loaded.
|
|
4
|
+
* @copyright 2023 New Relic Corporation. All rights reserved.
|
|
5
|
+
* @license Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { generateUuid } from './unique-id'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Provides a unique id for the current agent bundle
|
|
12
|
+
*/
|
|
13
|
+
export const bundleId = generateUuid()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function parseUrl (url) {
|
|
2
|
+
try {
|
|
3
|
+
const result = new URL(url)
|
|
4
|
+
|
|
5
|
+
return {
|
|
6
|
+
hostname: result.hostname,
|
|
7
|
+
port: result.port || result.protocol.startsWith('https') ? '443' : '80',
|
|
8
|
+
pathname: result.pathname,
|
|
9
|
+
protocol: result.protocol.replace(':', ''),
|
|
10
|
+
sameOrigin: false
|
|
11
|
+
}
|
|
12
|
+
} catch (err) {
|
|
13
|
+
return {}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const defaults = {}
|
|
2
|
+
export const gosNREUM = jest.fn(() => ({}))
|
|
3
|
+
export const gosNREUMInfo = jest.fn(() => ({}))
|
|
4
|
+
export const gosNREUMLoaderConfig = jest.fn(() => ({}))
|
|
5
|
+
export const gosNREUMInit = jest.fn(() => ({}))
|
|
6
|
+
export const gosNREUMOriginals = jest.fn(() => ({}))
|
|
7
|
+
export const gosNREUMInitializedAgents = jest.fn(() => ({}))
|
|
8
|
+
export const addToNREUM = jest.fn(() => ({}))
|
|
9
|
+
export const NREUMinitialized = jest.fn(() => ({}))
|
|
10
|
+
export const gosCDN = jest.fn(() => ({}))
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
* This module is used directly by: session_trace.
|
|
8
8
|
* It is also called by -> wrapXhr <-, so see "wrap-xhr.js" for features that use this indirectly.
|
|
9
9
|
*/
|
|
10
|
-
import { ee as baseEE } from '../event-emitter/contextual-ee'
|
|
10
|
+
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
|
|
11
11
|
import { createWrapperWithEmitter as wfn } from './wrap-function'
|
|
12
12
|
import { getOrSet } from '../util/get-or-set'
|
|
13
13
|
import { globalScope, isBrowserScope } from '../constants/runtime'
|
|
14
14
|
|
|
15
15
|
const wrapped = {}
|
|
16
|
-
const XHR = XMLHttpRequest
|
|
16
|
+
const XHR = globalScope.XMLHttpRequest
|
|
17
17
|
const ADD_EVENT_LISTENER = 'addEventListener'
|
|
18
18
|
const REMOVE_EVENT_LISTENER = 'removeEventListener'
|
|
19
|
+
const flag = `nr@wrapped:${contextId}`
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Wraps `addEventListener` and `removeEventListener` on: global scope; the prototype of `XMLHttpRequest`, and
|
|
@@ -48,7 +49,7 @@ export function wrapEvents (sharedEE) {
|
|
|
48
49
|
return
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
var wrapped = getOrSet(originalListener,
|
|
52
|
+
var wrapped = getOrSet(originalListener, flag, function () {
|
|
52
53
|
var listener = {
|
|
53
54
|
object: wrapHandleEvent,
|
|
54
55
|
function: originalListener
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
* @file Wraps `fetch` and related methods for instrumentation.
|
|
7
7
|
* This module is used by: ajax, spa.
|
|
8
8
|
*/
|
|
9
|
-
import { ee as baseEE } from '../event-emitter/contextual-ee'
|
|
9
|
+
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
|
|
10
10
|
import { globalScope } from '../constants/runtime'
|
|
11
|
-
import { flag } from './wrap-function'
|
|
12
11
|
|
|
13
12
|
var prefix = 'fetch-'
|
|
14
13
|
var bodyPrefix = prefix + 'body-'
|
|
@@ -16,7 +15,6 @@ var bodyMethods = ['arrayBuffer', 'blob', 'json', 'text', 'formData']
|
|
|
16
15
|
var Req = globalScope.Request
|
|
17
16
|
var Res = globalScope.Response
|
|
18
17
|
var proto = 'prototype'
|
|
19
|
-
var ctxId = 'nr@context'
|
|
20
18
|
|
|
21
19
|
const wrapped = {}
|
|
22
20
|
|
|
@@ -76,7 +74,7 @@ export function wrapFetch (sharedEE) {
|
|
|
76
74
|
// we are wrapping args in an array so we can preserve the reference
|
|
77
75
|
ee.emit(prefix + 'before-start', [args], ctx)
|
|
78
76
|
var dtPayload
|
|
79
|
-
if (ctx[
|
|
77
|
+
if (ctx[contextId] && ctx[contextId].dt) dtPayload = ctx[contextId].dt
|
|
80
78
|
|
|
81
79
|
var origPromiseFromFetch = fn.apply(this, args)
|
|
82
80
|
|