Skip to content

Commit 3fb63cb

Browse files
committed
Merge branch 'NR-443292-dom-mutations' into tmp-user-frustrations
2 parents aca15df + 4ed61fc commit 3fb63cb

File tree

5 files changed

+69
-45
lines changed

5 files changed

+69
-45
lines changed

.github/actions/build-ab/templates/released.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// config
22
window.NREUM={
33
init: {
4+
feature_flags: ['soft_nav'],
45
distributed_tracing: {
56
enabled: true
67
},

src/common/harvest/harvester.js

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,24 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
135135

136136
const fullUrl = `${url}?${baseParams}${payloadParams}`
137137
const gzip = !!qs?.attributes?.includes('gzip')
138-
if (!gzip) {
139-
if (endpoint !== EVENTS) body = stringify(body) // all features going to 'events' endpoint should already be serialized & stringified
140-
// Warn--once per endpoint--if the agent tries to send large payloads
141-
if (body.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) warn(28, endpoint)
142-
}
138+
139+
// all gzipped data is already in the correct format and needs no transformation
140+
// all features going to 'events' endpoint should already be serialized & stringified
141+
let stringBody = gzip || endpoint === EVENTS ? body : stringify(body)
143142

144143
// If body is null, undefined, or an empty object or array after stringifying, send an empty string instead.
145-
if (!body || body.length === 0 || body === '{}' || body === '[]') body = ''
144+
if (!stringBody || stringBody.length === 0 || stringBody === '{}' || stringBody === '[]') stringBody = ''
145+
146+
// Warn--once per endpoint--if the agent tries to send large payloads
147+
if (endpoint !== BLOBS && stringBody.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) warn(28, endpoint)
146148

147149
const headers = [{ key: 'content-type', value: 'text/plain' }]
148150

149151
/* Since workers don't support sendBeacon right now, they can only use XHR method.
150152
Because they still do permit synch XHR, the idea is that at final harvest time (worker is closing),
151153
we just make a BLOCKING request--trivial impact--with the remaining data as a temp fill-in for sendBeacon.
152154
Following the removal of img-element method. */
153-
let result = submitMethod({ url: fullUrl, body, sync: localOpts.isFinalHarvest && isWorkerScope, headers })
155+
let result = submitMethod({ url: fullUrl, body: stringBody, sync: localOpts.isFinalHarvest && isWorkerScope, headers })
154156

155157
if (!localOpts.isFinalHarvest && cbFinished) { // final harvests don't hold onto buffer data (shouldRetryOnFail is false), so cleanup isn't needed
156158
if (submitMethod === xhrMethod) {
@@ -176,17 +178,23 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
176178
}
177179

178180
function trackHarvestMetadata () {
179-
const hasReplay = baseParams.includes('hr=1')
180-
const hasTrace = baseParams.includes('ht=1')
181-
const hasError = qs?.attributes?.includes('hasError=true')
182-
183-
handle('harvest-metadata', [{
184-
[featureName]: {
185-
...(hasReplay && { hasReplay }),
186-
...(hasTrace && { hasTrace }),
187-
...(hasError && { hasError })
188-
}
189-
}], undefined, FEATURE_NAMES.metrics, agentRef.ee)
181+
try {
182+
if (featureName === FEATURE_NAMES.jserrors && !body?.err) return
183+
184+
const hasReplay = baseParams.includes('hr=1')
185+
const hasTrace = baseParams.includes('ht=1')
186+
const hasError = qs?.attributes?.includes('hasError=true')
187+
188+
handle('harvest-metadata', [{
189+
[featureName]: {
190+
...(hasReplay && { hasReplay }),
191+
...(hasTrace && { hasTrace }),
192+
...(hasError && { hasError })
193+
}
194+
}], undefined, FEATURE_NAMES.metrics, agentRef.ee)
195+
} catch (err) {
196+
// do nothing
197+
}
190198
}
191199
}
192200

src/common/url/extract-url.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import { globalScope } from '../constants/runtime'
66
import { gosNREUMOriginals } from '../window/nreum'
77

8+
/**
9+
* Extracts a URL from various target types.
10+
* @param {string|Request|URL} target - The target to extract the URL from. It can be a string, a Fetch Request object, or a URL object.
11+
* @returns {string|undefined} The extracted URL as a string, or undefined if the target type is not supported.
12+
*/
813
export function extractUrl (target) {
9-
if (typeof target === 'string') {
10-
return target
11-
} else if (typeof target === 'object' && target instanceof gosNREUMOriginals().o.REQ) {
12-
return target.url
13-
} else if (globalScope?.URL && typeof target === 'object' && target instanceof URL) {
14-
return target.href
15-
}
16-
return undefined
14+
if (typeof target === 'string') return target
15+
else if (target instanceof gosNREUMOriginals().o.REQ) return target.url
16+
else if (globalScope?.URL && target instanceof URL) return target.href
1717
}

src/features/generic_events/instrument/index.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,24 @@ export class Instrument extends InstrumentBase {
8787

8888
wrapFetch(this.ee)
8989
wrapXhr(this.ee)
90-
this.ee.on('send-xhr-start', (_, xhr) => {
91-
emitIfNonAgentTraffic.call(this, parseUrl(xhr.responseURL))
90+
this.ee.on('open-xhr-start', (args, xhr) => {
91+
if (!isInternalTraffic(args[1])) {
92+
xhr.addEventListener('readystatechange', () => {
93+
if (xhr.readyState === 2) { // HEADERS_RECEIVED
94+
handle('uaXhr', [], undefined, FEATURE_NAMES.genericEvents, this.ee)
95+
}
96+
})
97+
}
9298
})
9399
this.ee.on('fetch-start', (fetchArguments) => {
94-
if (fetchArguments.length >= 1) { emitIfNonAgentTraffic.call(this, parseUrl(extractUrl(fetchArguments[0]))) }
100+
if (fetchArguments.length >= 1 && !isInternalTraffic(extractUrl(fetchArguments[0]))) {
101+
handle('uaXhr', [], undefined, FEATURE_NAMES.genericEvents, this.ee)
102+
}
95103
})
96104

97-
function emitIfNonAgentTraffic (parsedUrl) {
98-
try {
99-
let host
100-
if (parsedUrl) host = parsedUrl.hostname + ':' + parsedUrl.port
101-
if (host && !agentRef.beacons.includes(host)) {
102-
handle('uaXhr', [], undefined, FEATURE_NAMES.genericEvents, this.ee)
103-
}
104-
} catch {}
105+
function isInternalTraffic (url) {
106+
const parsedUrl = parseUrl(url)
107+
return agentRef.beacons.includes(parsedUrl.hostname + ':' + parsedUrl.port)
105108
}
106109

107110
/** If any of the sources are active, import the aggregator. otherwise deregister */

tests/components/generic_events/instrument/index.test.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,25 +179,37 @@ describe('User frustrations - XMLHttpRequest', () => {
179179
class MockXMLHttpRequest {
180180
constructor () {
181181
this.readyState = 0
182-
this.status = 200
182+
this.status = 0
183183
this.responseText = ''
184184
this.responseURL = ''
185-
this.onreadystatechange = null
185+
this._url = ''
186+
}
187+
188+
onreadystatechange (url) {
189+
if (this.readyState === 1) {
190+
this._url = url
191+
} else if (this.readyState === 2) {
192+
this.responseURL = this._url
193+
}
194+
if (this._onreadystatechange) this._onreadystatechange()
186195
}
187196

188197
open (method, url) {
189198
this.method = method
190-
this.responseURL = url
191199
this.readyState = 1
200+
this.onreadystatechange(url)
192201
}
193202

194203
send () {
195-
this.readyState = 4
204+
this.readyState = 2
196205
this.responseText = 'Mock response'
197-
if (this.onreadystatechange) {
198-
this.onreadystatechange()
199-
}
206+
this.status = 200
207+
this.onreadystatechange()
200208
}
201209

202-
addEventListener = jest.fn()
210+
addEventListener = (event, handler) => {
211+
if (event === 'readystatechange' && typeof handler === 'function') {
212+
this._onreadystatechange = handler
213+
}
214+
}
203215
}

0 commit comments

Comments
 (0)