Skip to content

Commit e2dbb2e

Browse files
chargomeclaude
andcommitted
fix(node): use process.on instead of process.once for beforeExit listener
Fixes the beforeExit listener to fire on every invocation in serverless warm starts (e.g. AWS Lambda). Also properly removes the old listener on re-init to avoid accumulation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2dae3ce commit e2dbb2e

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

packages/node-core/src/integrations/nodeRuntimeMetrics.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export const nodeRuntimeMetricsIntegration = defineIntegration((options: NodeRun
9494
const needsCpu = collect.cpuUtilization || collect.cpuTime;
9595

9696
let intervalId: ReturnType<typeof setInterval> | undefined;
97+
let beforeExitListener: (() => void) | undefined;
9798
let prevCpuUsage: NodeJS.CpuUsage | undefined;
9899
let prevElu: ReturnType<typeof performance.eventLoopUtilization> | undefined;
99100
let prevFlushTime: number = 0;
@@ -192,20 +193,26 @@ export const nodeRuntimeMetricsIntegration = defineIntegration((options: NodeRun
192193
}
193194
prevFlushTime = _INTERNAL_safeDateNow();
194195

195-
// Guard against double setup (e.g. re-init).
196+
// Guard against double setup (e.g. re-init): clean up previous resources.
196197
if (intervalId) {
197198
clearInterval(intervalId);
198199
}
200+
if (beforeExitListener) {
201+
process.off('beforeExit', beforeExitListener);
202+
}
203+
199204
intervalId = setInterval(collectMetrics, collectionIntervalMs);
200205
// Do not keep the process alive solely for metric collection.
201206
intervalId.unref();
202207

203-
// Collect and flush at the end of every invocation. In non-serverless environments
204-
// flushIfServerless is a no-op, so this is safe to call unconditionally.
205-
process.once('beforeExit', () => {
208+
// Collect and flush at the end of every invocation. Uses process.on (not once) so
209+
// that serverless warm starts (e.g. Lambda) trigger a flush on every invocation.
210+
// In non-serverless environments flushIfServerless is a no-op.
211+
beforeExitListener = () => {
206212
collectMetrics();
207213
void flushIfServerless();
208-
});
214+
};
215+
process.on('beforeExit', beforeExitListener);
209216
},
210217
};
211218
});

0 commit comments

Comments
 (0)