taist 0.2.12 → 0.2.13
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/lib/trace-reporter.js +90 -31
- package/package.json +1 -1
package/lib/trace-reporter.js
CHANGED
|
@@ -35,6 +35,8 @@ export class TraceReporter extends EventEmitter {
|
|
|
35
35
|
this.workerId = options.workerId || process.pid;
|
|
36
36
|
this.closed = false;
|
|
37
37
|
this.shuttingDown = false; // Prevents race between shutdown signal and SIGTERM
|
|
38
|
+
this.pendingWrites = 0; // Track writes that have been initiated but callback hasn't fired
|
|
39
|
+
this.pendingWriteResolvers = []; // Resolvers to call when pendingWrites reaches 0
|
|
38
40
|
|
|
39
41
|
logger.debug("[reporter] Created with socketPath:", this.socketPath, "flushImmediate:", this.flushImmediate);
|
|
40
42
|
|
|
@@ -162,50 +164,84 @@ export class TraceReporter extends EventEmitter {
|
|
|
162
164
|
|
|
163
165
|
/**
|
|
164
166
|
* Handle shutdown signal from collector.
|
|
165
|
-
*
|
|
167
|
+
* Waits for pending writes and flushes buffer before closing.
|
|
166
168
|
*/
|
|
167
169
|
_handleShutdown() {
|
|
168
170
|
if (this.closed || this.shuttingDown) return;
|
|
169
171
|
|
|
172
|
+
const lifecycleDebug = process.env.TAIST_TRACE_LIFECYCLE === 'true';
|
|
173
|
+
|
|
170
174
|
// Set flag immediately to prevent exit handlers from interfering
|
|
171
175
|
this.shuttingDown = true;
|
|
172
176
|
this._stopFlushTimer();
|
|
173
177
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
178
|
+
if (lifecycleDebug) {
|
|
179
|
+
console.log(`[LIFECYCLE reporter] [${Date.now()}] _handleShutdown called, pendingWrites:`, this.pendingWrites, 'buffer:', this.buffer.length);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Wait for any pending writes to complete first
|
|
183
|
+
const waitForPendingWrites = () => {
|
|
184
|
+
return new Promise((resolve) => {
|
|
185
|
+
if (this.pendingWrites === 0) {
|
|
186
|
+
resolve();
|
|
187
|
+
} else {
|
|
188
|
+
if (lifecycleDebug) {
|
|
189
|
+
console.log('[LIFECYCLE reporter] Waiting for', this.pendingWrites, 'pending writes...');
|
|
190
|
+
}
|
|
191
|
+
this.pendingWriteResolvers.push(resolve);
|
|
192
|
+
// Safety timeout - don't wait forever
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
if (lifecycleDebug && this.pendingWrites > 0) {
|
|
195
|
+
console.log('[LIFECYCLE reporter] Timeout waiting for pending writes, still have:', this.pendingWrites);
|
|
196
|
+
}
|
|
197
|
+
resolve();
|
|
198
|
+
}, 1000);
|
|
199
|
+
}
|
|
181
200
|
});
|
|
201
|
+
};
|
|
182
202
|
|
|
183
|
-
|
|
203
|
+
// Wait for pending writes, then flush any remaining buffer, then close
|
|
204
|
+
waitForPendingWrites().then(() => {
|
|
205
|
+
if (lifecycleDebug) {
|
|
206
|
+
console.log('[LIFECYCLE reporter] Pending writes done, flushing remaining buffer:', this.buffer.length);
|
|
207
|
+
}
|
|
184
208
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
209
|
+
// Flush any remaining buffer
|
|
210
|
+
if (this.buffer.length > 0 && this.socket && this.connected) {
|
|
211
|
+
const traces = this.buffer.splice(0, this.buffer.length);
|
|
212
|
+
const message = JSON.stringify({
|
|
213
|
+
type: "batch",
|
|
214
|
+
workerId: this.workerId,
|
|
215
|
+
data: traces,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
logger.debug("[reporter] Shutdown flushing", traces.length, "traces");
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
// Write data
|
|
222
|
+
const flushed = this.socket.write(message + "\n");
|
|
223
|
+
|
|
224
|
+
if (flushed) {
|
|
225
|
+
// Data was written to kernel buffer, use setImmediate to allow
|
|
226
|
+
// the event loop to process and send the data before closing
|
|
227
|
+
setImmediate(() => {
|
|
228
|
+
this._gracefulClose();
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
// Buffer is full, wait for drain
|
|
232
|
+
this.socket.once('drain', () => {
|
|
233
|
+
logger.debug("[reporter] Drained, closing");
|
|
234
|
+
this._gracefulClose();
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
} catch (err) {
|
|
238
|
+
logger.debug("[reporter] Write error:", err.message);
|
|
239
|
+
this.close();
|
|
201
240
|
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
this.close();
|
|
241
|
+
} else {
|
|
242
|
+
this._gracefulClose();
|
|
205
243
|
}
|
|
206
|
-
}
|
|
207
|
-
this._gracefulClose();
|
|
208
|
-
}
|
|
244
|
+
});
|
|
209
245
|
}
|
|
210
246
|
|
|
211
247
|
/**
|
|
@@ -335,8 +371,31 @@ export class TraceReporter extends EventEmitter {
|
|
|
335
371
|
data: traces,
|
|
336
372
|
});
|
|
337
373
|
|
|
374
|
+
// Track pending write
|
|
375
|
+
this.pendingWrites++;
|
|
376
|
+
if (lifecycleDebug) {
|
|
377
|
+
console.log(`[LIFECYCLE reporter] [${Date.now()}] pendingWrites++, now:`, this.pendingWrites);
|
|
378
|
+
}
|
|
379
|
+
|
|
338
380
|
return new Promise((resolve, reject) => {
|
|
339
381
|
const writeResult = this.socket.write(message + "\n", (err) => {
|
|
382
|
+
// Write completed (success or error)
|
|
383
|
+
this.pendingWrites--;
|
|
384
|
+
if (lifecycleDebug) {
|
|
385
|
+
console.log(`[LIFECYCLE reporter] [${Date.now()}] pendingWrites--, now:`, this.pendingWrites);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// If shutdown is waiting for pending writes, notify it
|
|
389
|
+
if (this.pendingWrites === 0 && this.pendingWriteResolvers.length > 0) {
|
|
390
|
+
if (lifecycleDebug) {
|
|
391
|
+
console.log('[LIFECYCLE reporter] All pending writes complete, notifying shutdown');
|
|
392
|
+
}
|
|
393
|
+
const resolvers = this.pendingWriteResolvers.splice(0);
|
|
394
|
+
for (const resolver of resolvers) {
|
|
395
|
+
resolver();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
340
399
|
if (err) {
|
|
341
400
|
if (lifecycleDebug) console.log('[LIFECYCLE reporter] WRITE CALLBACK error:', err.message);
|
|
342
401
|
// Put traces back in buffer on failure
|