@newrelic/browser-agent 1.256.0 → 1.256.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,13 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.256.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.256.0...v1.256.1) (2024-04-15)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Revert "Generate PTID in Agent" ([#976](https://github.com/newrelic/newrelic-browser-agent/issues/976)) ([34b317f](https://github.com/newrelic/newrelic-browser-agent/commit/34b317fe577487af56d48861b7f256ec8d644d69))
12
+
6
13
  ## [1.256.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.255.0...v1.256.0) (2024-04-11)
7
14
 
8
15
 
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = exports.VERSION = "1.256.0";
15
+ const VERSION = exports.VERSION = "1.256.1";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = exports.VERSION = "1.256.0";
15
+ const VERSION = exports.VERSION = "1.256.1";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -186,7 +186,6 @@ class Harvest extends _sharedContext.SharedContext {
186
186
  const cbResult = {
187
187
  sent: this.status !== 0,
188
188
  status: this.status,
189
- failed: this.status === 0 || this.status >= 400,
190
189
  xhr: this,
191
190
  fullUrl
192
191
  };
@@ -57,11 +57,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
57
57
  // Very unlikely, but in case the existing XMLHttpRequest.prototype object on the page couldn't be wrapped.
58
58
  if (!this.agentRuntime.xhrWrappable) return;
59
59
  this.resourceObserver = argsObj?.resourceObserver; // undefined if observer couldn't be created
60
- this.ptid = this.agentRuntime.ptid;
60
+ this.ptid = '';
61
61
  this.trace = {};
62
62
  this.nodeCount = 0;
63
63
  this.sentTrace = null;
64
- this.everSent = false;
65
64
  this.harvestTimeSeconds = (0, _config.getConfigurationValue)(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10;
66
65
  this.maxNodesPerHarvest = (0, _config.getConfigurationValue)(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000;
67
66
  /**
@@ -113,7 +112,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
113
112
  this.isStandalone = false;
114
113
  if (prevMode === _constants2.MODE.ERROR && this.#scheduler) {
115
114
  this.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
116
- this.#scheduler.runHarvest({});
115
+ this.#scheduler.runHarvest({
116
+ needResponse: true
117
+ });
117
118
  } else {
118
119
  controlTraceOp(_constants2.MODE.FULL);
119
120
  }
@@ -136,7 +137,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
136
137
  sessionTraceMode: _constants2.MODE.OFF
137
138
  });
138
139
  operationalGate.permanentlyDecide(false);
139
- if (mostRecentModeKnown === _constants2.MODE.FULL) this.#scheduler?.runHarvest({}); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
140
+ if (mostRecentModeKnown === _constants2.MODE.FULL) this.#scheduler?.runHarvest(); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
140
141
  this.#scheduler?.stopTimer(true); // the 'true' arg here will forcibly block any future call to runHarvest, so the last runHarvest above must be prior
141
142
  this.#scheduler = null;
142
143
  };
@@ -155,7 +156,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
155
156
  - if trace switches to Full mode, harvest should start (prev: Error) if not already running (prev: Full). */
156
157
  this.ee.on(_constants2.SESSION_EVENTS.RESUME, () => {
157
158
  const updatedTraceMode = sessionEntity.state.sessionTraceMode;
158
- if (updatedTraceMode === _constants2.MODE.OFF) stopTracePerm();else if (updatedTraceMode === _constants2.MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({});
159
+ if (updatedTraceMode === _constants2.MODE.OFF) stopTracePerm();else if (updatedTraceMode === _constants2.MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({
160
+ needResponse: true
161
+ });
159
162
  mostRecentModeKnown = updatedTraceMode;
160
163
  });
161
164
  this.ee.on(_constants2.SESSION_EVENTS.PAUSE, () => {
@@ -246,12 +249,15 @@ class Aggregate extends _aggregateBase.AggregateBase {
246
249
  retryDelay: this.harvestTimeSeconds
247
250
  }, this);
248
251
  this.#scheduler.harvest.on('resources', this.#prepareHarvest.bind(this));
249
- if (dontStartHarvestYet === false) this.#scheduler.runHarvest({}); // sends first stn harvest immediately
252
+ if (dontStartHarvestYet === false) this.#scheduler.runHarvest({
253
+ needResponse: true
254
+ }); // sends first stn harvest immediately
250
255
  startupBuffer.decide(true); // signal to ALLOW & process data in EE's buffer into internal nodes queued for next harvest
251
256
  }
252
257
  #onHarvestFinished(result) {
253
- if (result.sent && !result.failed && !this.#scheduler.started) {
254
- // continue interval harvest only after first call
258
+ if (result.sent && result.responseText && !this.ptid) {
259
+ // continue interval harvest only if ptid was returned by server on the first
260
+ this.agentRuntime.ptid = this.ptid = result.responseText;
255
261
  this.#scheduler.startTimer(this.harvestTimeSeconds);
256
262
  }
257
263
  if (result.sent && result.retry && this.sentTrace) {
@@ -267,18 +273,15 @@ class Aggregate extends _aggregateBase.AggregateBase {
267
273
  }
268
274
  #prepareHarvest(options) {
269
275
  if (this.isStandalone) {
270
- if (this.#scheduler.started) {
271
- if ((0, _now.now)() >= MAX_TRACE_DURATION) {
272
- // Perform a final harvest once we hit or exceed the max session trace time
273
- options.isFinalHarvest = true;
274
- this.operationalGate.permanentlyDecide(false);
275
- this.#scheduler.stopTimer(true);
276
- } else if (this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
277
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
278
- return;
279
- }
276
+ if (this.ptid && (0, _now.now)() >= MAX_TRACE_DURATION) {
277
+ // Perform a final harvest once we hit or exceed the max session trace time
278
+ options.isFinalHarvest = true;
279
+ this.operationalGate.permanentlyDecide(false);
280
+ this.#scheduler.stopTimer(true);
281
+ } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
282
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
283
+ return;
280
284
  }
281
- // else, we must be on the very first harvest (standalone mode), so go to next square
282
285
  } else {
283
286
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
284
287
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -60,7 +60,6 @@ function configure(agent) {
60
60
  agent.runSoftNavOverSpa &&= updatedInit.soft_navigations.enabled === true && updatedInit.feature_flags.includes('soft_nav');
61
61
  }
62
62
  runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
63
- runtime.ptid = agent.agentIdentifier;
64
63
  (0, _config.setRuntime)(agent.agentIdentifier, runtime);
65
64
  if (agent.api === undefined) agent.api = (0, _api.setAPI)(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
66
65
  if (agent.exposed === undefined) agent.exposed = exposed;
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Exposes the version of the agent
8
8
  */
9
- export const VERSION = "1.256.0";
9
+ export const VERSION = "1.256.1";
10
10
 
11
11
  /**
12
12
  * Exposes the build type of the agent
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Exposes the version of the agent
8
8
  */
9
- export const VERSION = "1.256.0";
9
+ export const VERSION = "1.256.1";
10
10
 
11
11
  /**
12
12
  * Exposes the build type of the agent
@@ -178,7 +178,6 @@ export class Harvest extends SharedContext {
178
178
  const cbResult = {
179
179
  sent: this.status !== 0,
180
180
  status: this.status,
181
- failed: this.status === 0 || this.status >= 400,
182
181
  xhr: this,
183
182
  fullUrl
184
183
  };
@@ -50,11 +50,10 @@ export class Aggregate extends AggregateBase {
50
50
  // Very unlikely, but in case the existing XMLHttpRequest.prototype object on the page couldn't be wrapped.
51
51
  if (!this.agentRuntime.xhrWrappable) return;
52
52
  this.resourceObserver = argsObj?.resourceObserver; // undefined if observer couldn't be created
53
- this.ptid = this.agentRuntime.ptid;
53
+ this.ptid = '';
54
54
  this.trace = {};
55
55
  this.nodeCount = 0;
56
56
  this.sentTrace = null;
57
- this.everSent = false;
58
57
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10;
59
58
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000;
60
59
  /**
@@ -106,7 +105,9 @@ export class Aggregate extends AggregateBase {
106
105
  this.isStandalone = false;
107
106
  if (prevMode === MODE.ERROR && this.#scheduler) {
108
107
  this.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
109
- this.#scheduler.runHarvest({});
108
+ this.#scheduler.runHarvest({
109
+ needResponse: true
110
+ });
110
111
  } else {
111
112
  controlTraceOp(MODE.FULL);
112
113
  }
@@ -129,7 +130,7 @@ export class Aggregate extends AggregateBase {
129
130
  sessionTraceMode: MODE.OFF
130
131
  });
131
132
  operationalGate.permanentlyDecide(false);
132
- if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest({}); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
133
+ if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest(); // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
133
134
  this.#scheduler?.stopTimer(true); // the 'true' arg here will forcibly block any future call to runHarvest, so the last runHarvest above must be prior
134
135
  this.#scheduler = null;
135
136
  };
@@ -148,7 +149,9 @@ export class Aggregate extends AggregateBase {
148
149
  - if trace switches to Full mode, harvest should start (prev: Error) if not already running (prev: Full). */
149
150
  this.ee.on(SESSION_EVENTS.RESUME, () => {
150
151
  const updatedTraceMode = sessionEntity.state.sessionTraceMode;
151
- if (updatedTraceMode === MODE.OFF) stopTracePerm();else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({});
152
+ if (updatedTraceMode === MODE.OFF) stopTracePerm();else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({
153
+ needResponse: true
154
+ });
152
155
  mostRecentModeKnown = updatedTraceMode;
153
156
  });
154
157
  this.ee.on(SESSION_EVENTS.PAUSE, () => {
@@ -239,12 +242,15 @@ export class Aggregate extends AggregateBase {
239
242
  retryDelay: this.harvestTimeSeconds
240
243
  }, this);
241
244
  this.#scheduler.harvest.on('resources', this.#prepareHarvest.bind(this));
242
- if (dontStartHarvestYet === false) this.#scheduler.runHarvest({}); // sends first stn harvest immediately
245
+ if (dontStartHarvestYet === false) this.#scheduler.runHarvest({
246
+ needResponse: true
247
+ }); // sends first stn harvest immediately
243
248
  startupBuffer.decide(true); // signal to ALLOW & process data in EE's buffer into internal nodes queued for next harvest
244
249
  }
245
250
  #onHarvestFinished(result) {
246
- if (result.sent && !result.failed && !this.#scheduler.started) {
247
- // continue interval harvest only after first call
251
+ if (result.sent && result.responseText && !this.ptid) {
252
+ // continue interval harvest only if ptid was returned by server on the first
253
+ this.agentRuntime.ptid = this.ptid = result.responseText;
248
254
  this.#scheduler.startTimer(this.harvestTimeSeconds);
249
255
  }
250
256
  if (result.sent && result.retry && this.sentTrace) {
@@ -260,18 +266,15 @@ export class Aggregate extends AggregateBase {
260
266
  }
261
267
  #prepareHarvest(options) {
262
268
  if (this.isStandalone) {
263
- if (this.#scheduler.started) {
264
- if (now() >= MAX_TRACE_DURATION) {
265
- // Perform a final harvest once we hit or exceed the max session trace time
266
- options.isFinalHarvest = true;
267
- this.operationalGate.permanentlyDecide(false);
268
- this.#scheduler.stopTimer(true);
269
- } else if (this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
270
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
271
- return;
272
- }
269
+ if (this.ptid && now() >= MAX_TRACE_DURATION) {
270
+ // Perform a final harvest once we hit or exceed the max session trace time
271
+ options.isFinalHarvest = true;
272
+ this.operationalGate.permanentlyDecide(false);
273
+ this.#scheduler.stopTimer(true);
274
+ } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
275
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
276
+ return;
273
277
  }
274
- // else, we must be on the very first harvest (standalone mode), so go to next square
275
278
  } else {
276
279
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
277
280
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -54,7 +54,6 @@ export function configure(agent) {
54
54
  agent.runSoftNavOverSpa &&= updatedInit.soft_navigations.enabled === true && updatedInit.feature_flags.includes('soft_nav');
55
55
  }
56
56
  runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
57
- runtime.ptid = agent.agentIdentifier;
58
57
  setRuntime(agent.agentIdentifier, runtime);
59
58
  if (agent.api === undefined) agent.api = setAPI(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
60
59
  if (agent.exposed === undefined) agent.exposed = exposed;
@@ -3,11 +3,10 @@ export class Aggregate extends AggregateBase {
3
3
  constructor(agentIdentifier: any, aggregator: any, argsObj: any);
4
4
  agentRuntime: any;
5
5
  resourceObserver: any;
6
- ptid: any;
6
+ ptid: string | undefined;
7
7
  trace: {} | undefined;
8
8
  nodeCount: number | undefined;
9
9
  sentTrace: {} | null | undefined;
10
- everSent: boolean | undefined;
11
10
  harvestTimeSeconds: any;
12
11
  maxNodesPerHarvest: any;
13
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAiCA;IACE,2BAAiC;IAGjC,iEA6IC;IA3IC,kBAA+C;IAK/C,sBAAiD;IACjD,UAAkC;IAClC,sBAAe;IACf,8BAAkB;IAClB,iCAAqB;IACrB,8BAAqB;IACrB,wBAA0G;IAC1G,wBAA4G;IAC5G;;4EAEwE;IACxE,kCAAyB;IAGzB,0CAAsC;IA0HxC,sEAcC;IA8CD,oDAOC;IAGD,oCAwBC;IAGD,uEAkBC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDASC;IAID,qCAkBC;IAGD,qEAUC;IAGD,mEAUC;IAGD,yBAeC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAGD;;;;;;;YAkCM;0GAC8F;;YAE9F;0FAC8E;;YAE9E,4IAA4I;;;;;;MAMjJ;IAED,mEA6BC;;CACF;8BAhhB6B,4BAA4B;6BAF7B,2BAA2B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAiCA;IACE,2BAAiC;IAGjC,iEA4IC;IA1IC,kBAA+C;IAK/C,sBAAiD;IACjD,yBAAc;IACd,sBAAe;IACf,8BAAkB;IAClB,iCAAqB;IACrB,wBAA0G;IAC1G,wBAA4G;IAC5G;;4EAEwE;IACxE,kCAAyB;IAGzB,0CAAsC;IA0HxC,sEAcC;IA6CD,oDAOC;IAGD,oCAwBC;IAGD,uEAkBC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDASC;IAID,qCAkBC;IAGD,qEAUC;IAGD,mEAUC;IAGD,yBAeC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAGD;;;;;;;YAkCM;0GAC8F;;YAE9F;0FAC8E;;YAE9E,4IAA4I;;;;;;MAMjJ;IAED,mEA6BC;;CACF;8BA9gB6B,4BAA4B;6BAF7B,2BAA2B"}
@@ -1 +1 @@
1
- {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/configure.js"],"names":[],"mappings":"AASA;;GAEG;AACH,oGAgDC"}
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../../src/loaders/configure/configure.js"],"names":[],"mappings":"AASA;;GAEG;AACH,oGA+CC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.256.0",
3
+ "version": "1.256.1",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -145,7 +145,7 @@ export class Harvest extends SharedContext {
145
145
  result.addEventListener('loadend', function () {
146
146
  // `this` refers to the XHR object in this scope, do not change this to a fat arrow
147
147
  // status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
148
- const cbResult = { sent: this.status !== 0, status: this.status, failed: this.status === 0 || this.status >= 400, xhr: this, fullUrl }
148
+ const cbResult = { sent: this.status !== 0, status: this.status, xhr: this, fullUrl }
149
149
  if (this.status === 429) {
150
150
  cbResult.retry = true
151
151
  cbResult.delay = harvestScope.tooManyRequestsDelay
@@ -43,11 +43,10 @@ export class Aggregate extends AggregateBase {
43
43
  if (!this.agentRuntime.xhrWrappable) return
44
44
 
45
45
  this.resourceObserver = argsObj?.resourceObserver // undefined if observer couldn't be created
46
- this.ptid = this.agentRuntime.ptid
46
+ this.ptid = ''
47
47
  this.trace = {}
48
48
  this.nodeCount = 0
49
49
  this.sentTrace = null
50
- this.everSent = false
51
50
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10
52
51
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000
53
52
  /**
@@ -100,7 +99,7 @@ export class Aggregate extends AggregateBase {
100
99
 
101
100
  if (prevMode === MODE.ERROR && this.#scheduler) {
102
101
  this.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
103
- this.#scheduler.runHarvest({})
102
+ this.#scheduler.runHarvest({ needResponse: true })
104
103
  } else {
105
104
  controlTraceOp(MODE.FULL)
106
105
  }
@@ -120,7 +119,7 @@ export class Aggregate extends AggregateBase {
120
119
  const stopTracePerm = () => {
121
120
  if (sessionEntity.state.sessionTraceMode !== MODE.OFF) sessionEntity.write({ sessionTraceMode: MODE.OFF })
122
121
  operationalGate.permanentlyDecide(false)
123
- if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest({}) // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
122
+ if (mostRecentModeKnown === MODE.FULL) this.#scheduler?.runHarvest() // allow queued nodes (past opGate) to final harvest, unless they were buffered in other modes
124
123
  this.#scheduler?.stopTimer(true) // the 'true' arg here will forcibly block any future call to runHarvest, so the last runHarvest above must be prior
125
124
  this.#scheduler = null
126
125
  }
@@ -139,7 +138,7 @@ export class Aggregate extends AggregateBase {
139
138
  this.ee.on(SESSION_EVENTS.RESUME, () => {
140
139
  const updatedTraceMode = sessionEntity.state.sessionTraceMode
141
140
  if (updatedTraceMode === MODE.OFF) stopTracePerm()
142
- else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({})
141
+ else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({ needResponse: true })
143
142
  mostRecentModeKnown = updatedTraceMode
144
143
  })
145
144
  this.ee.on(SESSION_EVENTS.PAUSE, () => { mostRecentModeKnown = sessionEntity.state.sessionTraceMode })
@@ -190,12 +189,13 @@ export class Aggregate extends AggregateBase {
190
189
  retryDelay: this.harvestTimeSeconds
191
190
  }, this)
192
191
  this.#scheduler.harvest.on('resources', this.#prepareHarvest.bind(this))
193
- if (dontStartHarvestYet === false) this.#scheduler.runHarvest({}) // sends first stn harvest immediately
192
+ if (dontStartHarvestYet === false) this.#scheduler.runHarvest({ needResponse: true }) // sends first stn harvest immediately
194
193
  startupBuffer.decide(true) // signal to ALLOW & process data in EE's buffer into internal nodes queued for next harvest
195
194
  }
196
195
 
197
196
  #onHarvestFinished (result) {
198
- if (result.sent && !result.failed && !this.#scheduler.started) { // continue interval harvest only after first call
197
+ if (result.sent && result.responseText && !this.ptid) { // continue interval harvest only if ptid was returned by server on the first
198
+ this.agentRuntime.ptid = this.ptid = result.responseText
199
199
  this.#scheduler.startTimer(this.harvestTimeSeconds)
200
200
  }
201
201
 
@@ -212,18 +212,15 @@ export class Aggregate extends AggregateBase {
212
212
 
213
213
  #prepareHarvest (options) {
214
214
  if (this.isStandalone) {
215
- if (this.#scheduler.started) {
216
- if (now() >= MAX_TRACE_DURATION) {
217
- // Perform a final harvest once we hit or exceed the max session trace time
218
- options.isFinalHarvest = true
219
- this.operationalGate.permanentlyDecide(false)
220
- this.#scheduler.stopTimer(true)
221
- } else if (this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
222
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
223
- return
224
- }
215
+ if (this.ptid && now() >= MAX_TRACE_DURATION) {
216
+ // Perform a final harvest once we hit or exceed the max session trace time
217
+ options.isFinalHarvest = true
218
+ this.operationalGate.permanentlyDecide(false)
219
+ this.#scheduler.stopTimer(true)
220
+ } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
221
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
222
+ return
225
223
  }
226
- // else, we must be on the very first harvest (standalone mode), so go to next square
227
224
  } else {
228
225
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
229
226
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -234,6 +231,7 @@ export class Aggregate extends AggregateBase {
234
231
  if (currentMode === MODE.OFF && Object.keys(this.trace).length === 0) return
235
232
  if (currentMode === MODE.ERROR) return // Trace in this mode should never be harvesting, even on unload
236
233
  }
234
+
237
235
  return this.takeSTNs(options.retry)
238
236
  }
239
237
 
@@ -52,7 +52,6 @@ export function configure (agent, opts = {}, loaderType, forceDrain) {
52
52
  ...(updatedInit.ajax.deny_list || []),
53
53
  ...(updatedInit.ajax.block_internal ? internalTrafficList : [])
54
54
  ]
55
- runtime.ptid = agent.agentIdentifier
56
55
  setRuntime(agent.agentIdentifier, runtime)
57
56
 
58
57
  if (agent.api === undefined) agent.api = setAPI(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa)