@newrelic/browser-agent 1.277.0 → 1.278.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/common/aggregate/event-aggregator.js +1 -1
  3. package/dist/cjs/common/config/init.js +1 -10
  4. package/dist/cjs/common/config/runtime.js +2 -1
  5. package/dist/cjs/common/constants/env.cdn.js +1 -1
  6. package/dist/cjs/common/constants/env.npm.js +1 -1
  7. package/dist/cjs/common/harvest/harvester.js +255 -0
  8. package/dist/cjs/common/harvest/types.js +5 -21
  9. package/dist/cjs/features/ajax/aggregate/index.js +2 -11
  10. package/dist/cjs/features/generic_events/aggregate/index.js +3 -10
  11. package/dist/cjs/features/jserrors/aggregate/index.js +3 -14
  12. package/dist/cjs/features/logging/aggregate/index.js +4 -12
  13. package/dist/cjs/features/metrics/aggregate/index.js +7 -15
  14. package/dist/cjs/features/page_view_event/aggregate/index.js +46 -48
  15. package/dist/cjs/features/page_view_timing/aggregate/index.js +0 -9
  16. package/dist/cjs/features/session_replay/aggregate/index.js +21 -43
  17. package/dist/cjs/features/session_replay/instrument/index.js +2 -1
  18. package/dist/cjs/features/session_replay/shared/recorder.js +6 -6
  19. package/dist/cjs/features/session_trace/aggregate/index.js +9 -24
  20. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +8 -2
  21. package/dist/cjs/features/soft_navigations/aggregate/index.js +4 -11
  22. package/dist/cjs/features/spa/aggregate/index.js +7 -10
  23. package/dist/cjs/features/utils/aggregate-base.js +66 -27
  24. package/dist/cjs/features/utils/event-buffer.js +0 -1
  25. package/dist/cjs/features/utils/event-store-manager.js +109 -0
  26. package/dist/cjs/features/utils/instrument-base.js +1 -10
  27. package/dist/cjs/loaders/features/features.js +16 -10
  28. package/dist/cjs/loaders/micro-agent.js +1 -0
  29. package/dist/esm/common/aggregate/event-aggregator.js +1 -1
  30. package/dist/esm/common/config/init.js +1 -10
  31. package/dist/esm/common/config/runtime.js +2 -1
  32. package/dist/esm/common/constants/env.cdn.js +1 -1
  33. package/dist/esm/common/constants/env.npm.js +1 -1
  34. package/dist/esm/common/harvest/harvester.js +249 -0
  35. package/dist/esm/common/harvest/types.js +5 -21
  36. package/dist/esm/features/ajax/aggregate/index.js +3 -12
  37. package/dist/esm/features/generic_events/aggregate/index.js +3 -10
  38. package/dist/esm/features/jserrors/aggregate/index.js +4 -15
  39. package/dist/esm/features/logging/aggregate/index.js +4 -12
  40. package/dist/esm/features/metrics/aggregate/index.js +7 -15
  41. package/dist/esm/features/page_view_event/aggregate/index.js +46 -48
  42. package/dist/esm/features/page_view_timing/aggregate/index.js +1 -10
  43. package/dist/esm/features/session_replay/aggregate/index.js +22 -44
  44. package/dist/esm/features/session_replay/instrument/index.js +2 -1
  45. package/dist/esm/features/session_replay/shared/recorder.js +6 -6
  46. package/dist/esm/features/session_trace/aggregate/index.js +9 -24
  47. package/dist/esm/features/session_trace/aggregate/trace/storage.js +8 -2
  48. package/dist/esm/features/soft_navigations/aggregate/index.js +5 -12
  49. package/dist/esm/features/spa/aggregate/index.js +8 -11
  50. package/dist/esm/features/utils/aggregate-base.js +66 -27
  51. package/dist/esm/features/utils/event-buffer.js +0 -1
  52. package/dist/esm/features/utils/event-store-manager.js +103 -0
  53. package/dist/esm/features/utils/instrument-base.js +1 -10
  54. package/dist/esm/loaders/features/features.js +15 -9
  55. package/dist/esm/loaders/micro-agent.js +1 -0
  56. package/dist/types/common/aggregate/event-aggregator.d.ts +1 -1
  57. package/dist/types/common/aggregate/event-aggregator.d.ts.map +1 -1
  58. package/dist/types/common/config/init.d.ts.map +1 -1
  59. package/dist/types/common/config/runtime.d.ts.map +1 -1
  60. package/dist/types/common/harvest/harvester.d.ts +16 -0
  61. package/dist/types/common/harvest/harvester.d.ts.map +1 -0
  62. package/dist/types/common/harvest/types.d.ts +8 -45
  63. package/dist/types/common/harvest/types.d.ts.map +1 -1
  64. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  65. package/dist/types/features/generic_events/aggregate/index.d.ts +0 -3
  66. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  67. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  68. package/dist/types/features/logging/aggregate/index.d.ts +0 -3
  69. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  70. package/dist/types/features/metrics/aggregate/index.d.ts +1 -1
  71. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  72. package/dist/types/features/page_view_event/aggregate/index.d.ts +6 -2
  73. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  74. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  75. package/dist/types/features/session_replay/aggregate/index.d.ts +12 -15
  76. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  77. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  78. package/dist/types/features/session_trace/aggregate/index.d.ts +0 -5
  79. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  80. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +8 -5
  81. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  82. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  83. package/dist/types/features/spa/aggregate/index.d.ts +0 -1
  84. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  85. package/dist/types/features/utils/aggregate-base.d.ts +12 -7
  86. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  87. package/dist/types/features/utils/event-buffer.d.ts +1 -2
  88. package/dist/types/features/utils/event-buffer.d.ts.map +1 -1
  89. package/dist/types/features/utils/event-store-manager.d.ts +43 -0
  90. package/dist/types/features/utils/event-store-manager.d.ts.map +1 -0
  91. package/dist/types/features/utils/instrument-base.d.ts +0 -1
  92. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  93. package/dist/types/loaders/features/features.d.ts +15 -12
  94. package/dist/types/loaders/features/features.d.ts.map +1 -1
  95. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  96. package/package.json +6 -6
  97. package/src/common/aggregate/event-aggregator.js +1 -1
  98. package/src/common/config/init.js +9 -10
  99. package/src/common/config/runtime.js +2 -1
  100. package/src/common/harvest/__mocks__/harvester.js +6 -0
  101. package/src/common/harvest/harvester.js +230 -0
  102. package/src/common/harvest/types.js +5 -21
  103. package/src/features/ajax/aggregate/index.js +3 -14
  104. package/src/features/generic_events/aggregate/index.js +3 -13
  105. package/src/features/jserrors/aggregate/index.js +4 -11
  106. package/src/features/logging/aggregate/index.js +4 -12
  107. package/src/features/metrics/aggregate/index.js +5 -12
  108. package/src/features/page_view_event/aggregate/index.js +38 -38
  109. package/src/features/page_view_timing/aggregate/index.js +1 -12
  110. package/src/features/session_replay/aggregate/index.js +19 -42
  111. package/src/features/session_replay/instrument/index.js +1 -1
  112. package/src/features/session_replay/shared/recorder.js +6 -6
  113. package/src/features/session_trace/aggregate/index.js +8 -25
  114. package/src/features/session_trace/aggregate/trace/storage.js +5 -2
  115. package/src/features/soft_navigations/aggregate/index.js +4 -12
  116. package/src/features/spa/aggregate/index.js +8 -11
  117. package/src/features/utils/aggregate-base.js +59 -27
  118. package/src/features/utils/event-buffer.js +0 -1
  119. package/src/features/utils/event-store-manager.js +101 -0
  120. package/src/features/utils/instrument-base.js +2 -8
  121. package/src/loaders/features/features.js +16 -9
  122. package/src/loaders/micro-agent.js +1 -0
  123. package/dist/cjs/common/harvest/harvest-scheduler.js +0 -168
  124. package/dist/cjs/common/harvest/harvest.js +0 -295
  125. package/dist/esm/common/harvest/harvest-scheduler.js +0 -160
  126. package/dist/esm/common/harvest/harvest.js +0 -286
  127. package/dist/types/common/harvest/harvest-scheduler.d.ts +0 -50
  128. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +0 -1
  129. package/dist/types/common/harvest/harvest.d.ts +0 -65
  130. package/dist/types/common/harvest/harvest.d.ts.map +0 -1
  131. package/src/common/harvest/__mocks__/harvest.js +0 -13
  132. package/src/common/harvest/harvest-scheduler.js +0 -166
  133. package/src/common/harvest/harvest.js +0 -282
@@ -1,282 +0,0 @@
1
- /*
2
- * Copyright 2020 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
-
6
- import { obj as encodeObj, param as encodeParam } from '../url/encode'
7
- import { stringify } from '../util/stringify'
8
- import * as submitData from '../util/submit-data'
9
- import { getLocation } from '../url/location'
10
- import { getInfo } from '../config/info'
11
- import { getConfigurationValue, getConfiguration } from '../config/init'
12
- import { getRuntime } from '../config/runtime'
13
- import { cleanURL } from '../url/clean-url'
14
- import { eventListenerOpts } from '../event-listener/event-listener-opts'
15
- import { SharedContext } from '../context/shared-context'
16
- import { VERSION } from '../constants/env'
17
- import { isWorkerScope } from '../constants/runtime'
18
- import { warn } from '../util/console'
19
- import { now } from '../timing/now'
20
-
21
- const warnings = {}
22
-
23
- /**
24
- * @typedef {import('./types.js').NetworkSendSpec} NetworkSendSpec
25
- * @typedef {import('./types.js').HarvestEndpointIdentifier} HarvestEndpointIdentifier
26
- * @typedef {import('./types.js').HarvestPayload} HarvestPayload
27
- * @typedef {import('./types.js').FeatureHarvestCallback} FeatureHarvestCallback
28
- * @typedef {import('./types.js').FeatureHarvestCallbackOptions} FeatureHarvestCallbackOptions
29
- */
30
- export class Harvest extends SharedContext {
31
- constructor (parent) {
32
- super(parent) // gets any allowed properties from the parent and stores them in `sharedContext`
33
-
34
- this.tooManyRequestsDelay = getConfigurationValue(this.sharedContext.agentIdentifier, 'harvest.tooManyRequestsDelay') || 60
35
- this.obfuscator = getRuntime(this.sharedContext.agentIdentifier).obfuscator
36
-
37
- this._events = {}
38
- }
39
-
40
- /**
41
- * Initiate a harvest from multiple sources. An event that corresponds to the endpoint
42
- * name is emitted, which gives any listeners the opportunity to provide payload data.
43
- * Note: Used by page_action
44
- * @param {NetworkSendSpec} spec Specification for sending data
45
- */
46
- sendX (spec = {}) {
47
- const submitMethod = submitData.getSubmitMethod({ isFinalHarvest: spec.opts?.unload })
48
- const options = {
49
- retry: !spec.opts?.unload && submitMethod === submitData.xhr,
50
- isFinalHarvest: spec.opts?.unload === true
51
- }
52
- const payload = this.createPayload(spec.endpoint, options)
53
- const caller = this._send.bind(this)
54
- return caller({ ...spec, payload, submitMethod })
55
- }
56
-
57
- /**
58
- * Initiate a harvest call.
59
- * @param {NetworkSendSpec} spec Specification for sending data
60
- */
61
- send (spec = {}) {
62
- const caller = this._send.bind(this)
63
-
64
- return caller(spec)
65
- }
66
-
67
- /**
68
- * Initiate a harvest call. Typically used by `sendX` and `send` methods or called directly
69
- * for raw network calls.
70
- * @param {NetworkSendSpec} param0 Specification for sending data
71
- * @returns {boolean} True if the network call succeeded. For final harvest calls, the return
72
- * value should not be relied upon because network calls will be made asynchronously.
73
- */
74
- _send ({ endpoint, payload = {}, opts = {}, submitMethod, cbFinished, customUrl, raw, includeBaseParams = true }) {
75
- const info = getInfo(this.sharedContext.agentIdentifier)
76
- if (!info.errorBeacon) return false
77
-
78
- const agentRuntime = getRuntime(this.sharedContext.agentIdentifier)
79
- let { body, qs } = this.cleanPayload(payload)
80
-
81
- if (Object.keys(body).length === 0 && !opts?.sendEmptyBody) { // no payload body? nothing to send, just run onfinish stuff and return
82
- if (cbFinished) {
83
- cbFinished({ sent: false })
84
- }
85
- return false
86
- }
87
-
88
- const init = getConfiguration(this.sharedContext.agentIdentifier)
89
- const protocol = init.ssl === false ? 'http' : 'https'
90
- const perceviedBeacon = init.proxy.beacon || info.errorBeacon
91
- const endpointURLPart = endpoint !== 'rum' ? `/${endpoint}` : ''
92
- let url = `${protocol}://${perceviedBeacon}${endpointURLPart}/1/${info.licenseKey}`
93
- if (customUrl) url = customUrl
94
- if (raw) url = `${protocol}://${perceviedBeacon}/${endpoint}`
95
-
96
- const baseParams = !raw && includeBaseParams ? this.baseQueryString(qs, endpoint) : ''
97
- let payloadParams = encodeObj(qs, agentRuntime.maxBytes)
98
- if (!submitMethod) {
99
- submitMethod = submitData.getSubmitMethod({ isFinalHarvest: opts.unload })
100
- }
101
- if (baseParams === '' && payloadParams.startsWith('&')) {
102
- payloadParams = payloadParams.substring(1)
103
- }
104
-
105
- const fullUrl = `${url}?${baseParams}${payloadParams}`
106
- const gzip = !!qs?.attributes?.includes('gzip')
107
-
108
- if (!gzip) {
109
- if (endpoint !== 'events') body = stringify(body) // all features going to /events/ endpoint should already be serialized & stringified
110
- /** Warn --once per endpoint-- if the agent tries to send large payloads */
111
- if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(28, endpoint)
112
- }
113
-
114
- if (!body || body.length === 0 || body === '{}' || body === '[]') {
115
- // If body is null, undefined, or an empty object or array, send an empty string instead
116
- body = ''
117
- }
118
-
119
- const headers = []
120
-
121
- headers.push({ key: 'content-type', value: 'text/plain' })
122
-
123
- /* Since workers don't support sendBeacon right now, they can only use XHR method.
124
- Because they still do permit synch XHR, the idea is that at final harvest time (worker is closing),
125
- we just make a BLOCKING request--trivial impact--with the remaining data as a temp fill-in for sendBeacon.
126
- Following the removal of img-element method. */
127
- let result = submitMethod({ url: fullUrl, body, sync: opts.unload && (isWorkerScope), headers })
128
-
129
- if (!opts.unload && cbFinished && submitMethod === submitData.xhr) {
130
- const harvestScope = this
131
- result.addEventListener('loadend', function () {
132
- // `this` refers to the XHR object in this scope, do not change this to a fat arrow
133
- // status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
134
- const cbResult = { sent: this.status !== 0, status: this.status, xhr: this, fullUrl }
135
- if (this.status === 429) {
136
- cbResult.retry = true
137
- cbResult.delay = harvestScope.tooManyRequestsDelay
138
- } else if (this.status === 408 || this.status === 500 || this.status === 503) {
139
- cbResult.retry = true
140
- }
141
-
142
- if (opts.needResponse) {
143
- cbResult.responseText = this.responseText
144
- }
145
- cbFinished(cbResult)
146
- }, eventListenerOpts(false))
147
- } else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
148
- const harvestScope = this
149
- result.then(async function (response) {
150
- const status = response.status
151
- const cbResult = { sent: true, status, fullUrl, fetchResponse: response }
152
-
153
- if (response.status === 429) {
154
- cbResult.retry = true
155
- cbResult.delay = harvestScope.tooManyRequestsDelay
156
- } else if (status === 408 || status === 500 || status === 503) {
157
- cbResult.retry = true
158
- }
159
-
160
- if (opts.needResponse) {
161
- cbResult.responseText = await response.text()
162
- }
163
-
164
- cbFinished(cbResult)
165
- })
166
- }
167
-
168
- return result
169
- }
170
-
171
- // The stuff that gets sent every time.
172
- baseQueryString (qs, endpoint) {
173
- const runtime = getRuntime(this.sharedContext.agentIdentifier)
174
- const info = getInfo(this.sharedContext.agentIdentifier)
175
-
176
- const ref = this.obfuscator.obfuscateString(cleanURL(getLocation()))
177
- const hr = runtime?.session?.state.sessionReplayMode === 1 && endpoint !== 'jserrors'
178
-
179
- const qps = [
180
- 'a=' + info.applicationID,
181
- encodeParam('sa', (info.sa ? '' + info.sa : '')),
182
- encodeParam('v', VERSION),
183
- transactionNameParam(info),
184
- encodeParam('ct', runtime.customTransaction),
185
- '&rst=' + now(),
186
- '&ck=0', // ck param DEPRECATED - still expected by backend
187
- '&s=' + (runtime.session?.state.value || '0'), // the 0 id encaps all untrackable and default traffic
188
- encodeParam('ref', ref),
189
- encodeParam('ptid', (runtime.ptid ? '' + runtime.ptid : ''))
190
- ]
191
- if (hr) qps.push(encodeParam('hr', '1', qs))
192
- return qps.join('')
193
- }
194
-
195
- /**
196
- * Calls and accumulates data from registered harvesting functions based on
197
- * the endpoint being harvested.
198
- * @param {HarvestEndpointIdentifier} endpoint BAM endpoint identifier.
199
- * @param {FeatureHarvestCallbackOptions} options Options to be passed to the
200
- * feature harvest listener callback.
201
- * @returns {HarvestPayload} Payload object to transmit to the bam endpoint.
202
- */
203
- createPayload (endpoint, options) {
204
- const listeners = this._events[endpoint]
205
- const payload = {
206
- body: {},
207
- qs: {}
208
- }
209
-
210
- if (Array.isArray(listeners) && listeners.length > 0) {
211
- for (let i = 0; i < listeners.length; i++) {
212
- const singlePayload = listeners[i](options)
213
-
214
- if (singlePayload) {
215
- payload.body = {
216
- ...payload.body,
217
- ...(singlePayload.body || {})
218
- }
219
- payload.qs = {
220
- ...payload.qs,
221
- ...(singlePayload.qs || {})
222
- }
223
- }
224
- }
225
- }
226
-
227
- return payload
228
- }
229
-
230
- /**
231
- * Cleans and returns a payload object containing a body and qs
232
- * object with key/value pairs. KV pairs where the value is null,
233
- * undefined, or an empty string are removed to save on transmission
234
- * size.
235
- * @param {HarvestPayload} payload Payload to be sent to the endpoint.
236
- * @returns {HarvestPayload} Cleaned payload payload to be sent to the endpoint.
237
- */
238
- cleanPayload (payload = {}) {
239
- const clean = (input) => {
240
- if ((typeof Uint8Array !== 'undefined' && input instanceof Uint8Array) || Array.isArray(input)) return input
241
- if (typeof input === 'string') return input.length > 0 ? input : null
242
- return Object.entries(input || {})
243
- .reduce((accumulator, [key, value]) => {
244
- if ((typeof value === 'number') ||
245
- (typeof value === 'string' && value.length > 0) ||
246
- (typeof value === 'object' && Object.keys(value || {}).length > 0)
247
- ) {
248
- accumulator[key] = value
249
- }
250
-
251
- return accumulator
252
- }, {})
253
- }
254
-
255
- return {
256
- body: clean(payload.body),
257
- qs: clean(payload.qs)
258
- }
259
- }
260
-
261
- /**
262
- * Registers a function to be called when harvesting is triggered for a specific
263
- * endpoint.
264
- * @param {HarvestEndpointIdentifier} endpoint
265
- * @param {FeatureHarvestCallback} listener
266
- */
267
- on (endpoint, listener) {
268
- if (!Array.isArray(this._events[endpoint])) {
269
- this._events[endpoint] = []
270
- }
271
-
272
- this._events[endpoint].push(listener)
273
- }
274
- }
275
-
276
- // Constructs the transaction name param for the beacon URL.
277
- // Prefers the obfuscated transaction name over the plain text.
278
- // Falls back to making up a name.
279
- function transactionNameParam (info) {
280
- if (info.transactionName) return encodeParam('to', info.transactionName)
281
- return encodeParam('t', info.tNamePlain || 'Unnamed Transaction')
282
- }