Complete paired-room SSOT cleanup and logger singleton

This commit is contained in:
ejclaw
2026-04-07 05:12:22 +09:00
parent ae12b157be
commit 10e10b499c
18 changed files with 648 additions and 473 deletions

View File

@@ -1,12 +1,34 @@
import pino, { type Logger } from 'pino';
const serviceName = (process.env.ASSISTANT_NAME || 'claude').toLowerCase();
const isTestEnv =
process.env.VITEST === 'true' || process.env.NODE_ENV === 'test';
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
name: serviceName,
transport: { target: 'pino-pretty', options: { colorize: true } },
});
type LoggerGlobalState = typeof globalThis & {
__ejclawLogger?: Logger;
__ejclawProcessHandlersInstalled?: boolean;
};
const globalState = globalThis as LoggerGlobalState;
function createRootLogger(): Logger {
const baseOptions = {
level: process.env.LOG_LEVEL || 'info',
name: serviceName,
};
if (isTestEnv) {
return pino(baseOptions);
}
return pino({
...baseOptions,
transport: { target: 'pino-pretty', options: { colorize: true } },
});
}
export const logger =
globalState.__ejclawLogger ?? (globalState.__ejclawLogger = createRootLogger());
type LogBindings = Record<string, unknown>;
@@ -30,11 +52,17 @@ export function createScopedLogger(bindings: LogBindings): Logger {
}
// Route uncaught errors through pino so they get timestamps in stderr
process.on('uncaughtException', (err) => {
function handleUncaughtException(err: unknown): void {
logger.fatal({ err }, 'Uncaught exception');
process.exit(1);
});
}
process.on('unhandledRejection', (reason) => {
function handleUnhandledRejection(reason: unknown): void {
logger.error({ err: reason }, 'Unhandled rejection');
});
}
if (!globalState.__ejclawProcessHandlersInstalled) {
process.on('uncaughtException', handleUncaughtException);
process.on('unhandledRejection', handleUnhandledRejection);
globalState.__ejclawProcessHandlersInstalled = true;
}