Skip to content

Commit 58f3c52

Browse files
feat: Harvest traces early (#1532)
1 parent 346cd45 commit 58f3c52

File tree

17 files changed

+599
-286
lines changed

17 files changed

+599
-286
lines changed

src/common/wrap/wrap-events.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export function wrapEvents (sharedEE) {
4545
ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {
4646
var originalListener = args[1]
4747
if (originalListener === null ||
48-
(typeof originalListener !== 'function' && typeof originalListener !== 'object')
48+
(typeof originalListener !== 'function' && typeof originalListener !== 'object') ||
49+
(args[0] === 'newrelic') // ignore our own window events
4950
) {
5051
return
5152
}

src/features/session_trace/aggregate/index.js

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { applyFnToProps } from '../../../common/util/traverse'
1313
import { cleanURL } from '../../../common/url/clean-url'
1414
import { warn } from '../../../common/util/console'
1515

16-
const ERROR_MODE_SECONDS_WINDOW = 30 * 1000 // sliding window of nodes to track when simply monitoring (but not harvesting) in error mode
1716
/** Reserved room for query param attrs */
1817
const QUERY_PARAM_PADDING = 5000
1918
export class Aggregate extends AggregateBase {
@@ -29,8 +28,8 @@ export class Aggregate extends AggregateBase {
2928
this.everHarvested = false
3029
/** If the harvest module is harvesting */
3130
this.harvesting = false
32-
/** TraceStorage is the mechanism that holds, normalizes and aggregates ST nodes. It will be accessed and purged when harvests occur */
33-
this.events = new TraceStorage(this)
31+
/** TraceStorage is a middleware that decides how to format data before passing events to `this.events` */
32+
this.traceStorage = new TraceStorage(this)
3433

3534
/* This agg needs information about sampling (sts) and entitlements (st) to make the appropriate decisions on running */
3635
this.waitForFlags(['sts', 'st'])
@@ -64,9 +63,9 @@ export class Aggregate extends AggregateBase {
6463
})
6564

6665
if (typeof PerformanceNavigationTiming !== 'undefined') {
67-
this.events.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0])
66+
this.traceStorage.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0])
6867
} else {
69-
this.events.storeTiming(globalScope.performance?.timing, true)
68+
this.traceStorage.storeTiming(globalScope.performance?.timing, true)
7069
}
7170
}
7271

@@ -82,13 +81,13 @@ export class Aggregate extends AggregateBase {
8281
this.timeKeeper ??= this.agentRef.runtime.timeKeeper
8382

8483
/** The handlers set up by the Inst file */
85-
registerHandler('bst', (...args) => this.events.storeEvent(...args), this.featureName, this.ee)
86-
registerHandler('bstResource', (...args) => this.events.storeResources(...args), this.featureName, this.ee)
87-
registerHandler('bstHist', (...args) => this.events.storeHist(...args), this.featureName, this.ee)
88-
registerHandler('bstXhrAgg', (...args) => this.events.storeXhrAgg(...args), this.featureName, this.ee)
89-
registerHandler('bstApi', (...args) => this.events.storeNode(...args), this.featureName, this.ee)
90-
registerHandler('trace-jserror', (...args) => this.events.storeErrorAgg(...args), this.featureName, this.ee)
91-
registerHandler('pvtAdded', (...args) => this.events.processPVT(...args), this.featureName, this.ee)
84+
registerHandler('bst', (...args) => this.traceStorage.storeEvent(...args), this.featureName, this.ee)
85+
registerHandler('bstResource', (...args) => this.traceStorage.storeResources(...args), this.featureName, this.ee)
86+
registerHandler('bstHist', (...args) => this.traceStorage.storeHist(...args), this.featureName, this.ee)
87+
registerHandler('bstXhrAgg', (...args) => this.traceStorage.storeXhrAgg(...args), this.featureName, this.ee)
88+
registerHandler('bstApi', (...args) => this.traceStorage.storeNode(...args), this.featureName, this.ee)
89+
registerHandler('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee)
90+
registerHandler('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee)
9291

9392
if (this.mode !== MODE.FULL) {
9493
/** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
@@ -111,22 +110,26 @@ export class Aggregate extends AggregateBase {
111110
this.abort(3)
112111
return
113112
}
113+
114114
return true
115115
}
116116

117-
serializer ({ stns }) {
117+
serializer (stns) {
118118
if (!stns.length) return // there are no processed nodes
119119
this.everHarvested = true
120120
return applyFnToProps(stns, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')
121121
}
122122

123-
queryStringsBuilder ({ stns, earliestTimeStamp, latestTimeStamp }) {
123+
queryStringsBuilder (stns) {
124124
const firstSessionHarvest = !this.agentRef.runtime.session.state.traceHarvestStarted
125125
if (firstSessionHarvest) this.agentRef.runtime.session.write({ traceHarvestStarted: true })
126126
const hasReplay = this.agentRef.runtime.session.state.sessionReplayMode === 1
127127
const endUserId = this.agentRef.info.jsAttributes['enduser.id']
128128
const entityGuid = this.agentRef.runtime.appMetadata.agents?.[0]?.entityGuid
129129

130+
const earliestTimeStamp = stns.reduce((earliest, stn) => Math.min(earliest, stn.s), Infinity)
131+
const latestTimeStamp = stns.reduce((latest, stn) => Math.max(latest, stn.s), -Infinity)
132+
130133
/* The blob consumer expects the following and will reject if not supplied:
131134
* browser_monitoring_key
132135
* type
@@ -175,7 +178,7 @@ export class Aggregate extends AggregateBase {
175178
this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
176179
if (prevMode === MODE.OFF || !this.initialized) return this.initialize(this.mode, this.entitled)
177180
if (this.initialized) {
178-
this.events.trimSTNs(ERROR_MODE_SECONDS_WINDOW) // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
181+
this.traceStorage.trimSTNsByTime() // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
179182
this.agentRef.runtime.harvester.triggerHarvestFor(this)
180183
}
181184
}
@@ -188,4 +191,9 @@ export class Aggregate extends AggregateBase {
188191
this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
189192
this.events.clear()
190193
}
194+
195+
postHarvestCleanup (result) {
196+
this.traceStorage.clear() // clear the trace storage state
197+
super.postHarvestCleanup(result)
198+
}
191199
}

0 commit comments

Comments
 (0)