Skip to content

Commit 67a1007

Browse files
committed
fix: emit telemetry eagerly in dev --logs to avoid SIGINT race
The global SIGINT handler in cli.ts calls process.exit(0) synchronously, which terminates the process before withCommandRunTelemetry can flush. Emit telemetry before the blocking server loop, matching the existing browser-mode pattern.
1 parent 5939a7e commit 67a1007

1 file changed

Lines changed: 49 additions & 43 deletions

File tree

src/cli/commands/dev/command.tsx

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -381,51 +381,57 @@ export const registerDev = (program: Command) => {
381381
console.log(`Log: ${logger.getRelativeLogPath()}`);
382382
console.log(`Press Ctrl+C to stop\n`);
383383

384-
const devResult = await withCommandRunTelemetry(
385-
'dev',
386-
{
387-
dev_action: 'server' as const,
388-
ui_mode: 'terminal' as const,
389-
has_stream: false,
390-
agent_protocol: standardize(AgentProtocol, (config.protocol ?? 'http').toLowerCase()),
391-
invoke_count: 0,
392-
},
393-
async (): Promise<Result> => {
394-
await new Promise<void>((resolve, reject) => {
395-
const devCallbacks = {
396-
onLog: (level: string, msg: string) => {
397-
const prefix = level === 'error' ? '❌' : level === 'warn' ? '⚠️' : '→';
398-
console.log(`${prefix} ${msg}`);
399-
logger.log(msg, level === 'error' ? 'error' : 'info');
400-
},
401-
onExit: (code: number | null) => {
402-
console.log(`\nServer exited with code ${code ?? 0}`);
403-
logger.finalize(code === 0);
404-
if (code !== 0 && code !== null) {
405-
reject(new Error(`Server exited with code ${code}`));
406-
} else {
407-
resolve();
408-
}
409-
},
410-
};
411-
412-
const server = createDevServer(config, {
413-
port: actualPort,
414-
envVars: mergedEnvVars,
415-
callbacks: devCallbacks,
416-
});
417-
server.start().catch(reject);
418-
419-
process.once('SIGINT', () => {
420-
console.log('\nStopping server...');
421-
collector?.stop();
422-
server.kill();
423-
});
384+
// Emit telemetry eagerly before the blocking server loop.
385+
// The global SIGINT handler calls process.exit(0) synchronously,
386+
// which would prevent withCommandRunTelemetry from ever flushing.
387+
{
388+
const client = await TelemetryClientAccessor.get().catch(() => undefined);
389+
if (client) {
390+
client.emit('cli.command_run', 0, {
391+
command_group: 'dev',
392+
command: 'dev',
393+
exit_reason: 'success',
394+
dev_action: 'server',
395+
ui_mode: 'terminal',
396+
has_stream: false,
397+
agent_protocol: standardize(AgentProtocol, (config.protocol ?? 'http').toLowerCase()),
398+
invoke_count: 0,
424399
});
425-
return { success: true as const };
400+
await client.flush();
426401
}
427-
);
428-
if (!devResult.success) throw devResult.error;
402+
}
403+
404+
await new Promise<void>((resolve, reject) => {
405+
const devCallbacks = {
406+
onLog: (level: string, msg: string) => {
407+
const prefix = level === 'error' ? '❌' : level === 'warn' ? '⚠️' : '→';
408+
console.log(`${prefix} ${msg}`);
409+
logger.log(msg, level === 'error' ? 'error' : 'info');
410+
},
411+
onExit: (code: number | null) => {
412+
console.log(`\nServer exited with code ${code ?? 0}`);
413+
logger.finalize(code === 0);
414+
if (code !== 0 && code !== null) {
415+
reject(new Error(`Server exited with code ${code}`));
416+
} else {
417+
resolve();
418+
}
419+
},
420+
};
421+
422+
const server = createDevServer(config, {
423+
port: actualPort,
424+
envVars: mergedEnvVars,
425+
callbacks: devCallbacks,
426+
});
427+
server.start().catch(reject);
428+
429+
process.once('SIGINT', () => {
430+
console.log('\nStopping server...');
431+
collector?.stop();
432+
server.kill();
433+
});
434+
});
429435
process.exit(0);
430436
}
431437

0 commit comments

Comments
 (0)