diff --git a/packages/kernel-cli/CHANGELOG.md b/packages/kernel-cli/CHANGELOG.md index 01ef62cb9..6d2f04471 100644 --- a/packages/kernel-cli/CHANGELOG.md +++ b/packages/kernel-cli/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- The daemon log filters entries below a minimum severity, defaulting to `info`, so high-volume `debug` output (refcount churn and similar) no longer dominates `daemon.log`; set `$OCAP_DAEMON_LOG_LEVEL` to `debug` to record everything again ([#1008](https://github.com/MetaMask/ocap-kernel/pull/1008)) - Relay state files (`relay.pid`, `relay.addr`) now live in their own directory (default `~/.libp2p-relay`, overridable via `$LIBP2P_RELAY_HOME`) instead of under `$OCAP_HOME`, so one libp2p relay can serve daemons with different OCAP_HOMEs ([#952](https://github.com/MetaMask/ocap-kernel/pull/952)) ### Fixed diff --git a/packages/kernel-cli/src/commands/daemon-entry.ts b/packages/kernel-cli/src/commands/daemon-entry.ts index 5a091735f..77d96b00e 100644 --- a/packages/kernel-cli/src/commands/daemon-entry.ts +++ b/packages/kernel-cli/src/commands/daemon-entry.ts @@ -11,11 +11,41 @@ import { join } from 'node:path'; import { getOcapHome } from '../ocap-home.ts'; import { isProcessAlive } from '../utils.ts'; +// Mirror of @metamask/logger's level ordering (`logLevels` is not part +// of the package's public surface). Higher numbers are more severe. +// Declared above the file-scope logger construction so the transport +// factory doesn't hit a temporal-dead-zone reference when it's called +// during module init. +const LOG_LEVELS = { + debug: 1, + info: 2, + log: 3, + warn: 4, + error: 5, +} as const; + +type LogLevelName = keyof typeof LOG_LEVELS; + +/** + * Resolve the daemon's minimum log level from `OCAP_DAEMON_LOG_LEVEL`. + * Defaults to `info` so noisy `debug` entries (refcount churn etc.) + * are dropped; set the env var to `debug` to re-enable everything. + * + * @returns The minimum log level to record. + */ +function resolveMinLogLevel(): LogLevelName { + const raw = process.env.OCAP_DAEMON_LOG_LEVEL; + if (raw !== undefined && raw in LOG_LEVELS) { + return raw as LogLevelName; + } + return 'info'; +} + const ocapDir = getOcapHome(); const logPath = join(ocapDir, 'daemon.log'); const logger = new Logger({ tags: ['daemon'], - transports: [makeFileTransport(logPath)], + transports: [makeFileTransport(logPath, resolveMinLogLevel())], }); // Install exit-cause handlers at module load, before main() runs, so @@ -139,13 +169,20 @@ async function readDaemonPid(pidPath: string): Promise { } /** - * Create a file transport that writes logs to a file. + * Create a file transport that writes logs to a file, filtering out + * entries below `minLevel`. * * @param logFilePath - The log file path. + * @param minLevel - Minimum severity to write; entries below this are + * dropped silently. * @returns A log transport function. */ -function makeFileTransport(logFilePath: string) { +function makeFileTransport(logFilePath: string, minLevel: LogLevelName) { + const minIdx = LOG_LEVELS[minLevel]; return (entry: LogEntry): void => { + if (LOG_LEVELS[entry.level] < minIdx) { + return; + } const line = `[${new Date().toISOString()}] [${entry.level}] ${entry.message ?? ''} ${(entry.data ?? []).map(String).join(' ')}\n`; // eslint-disable-next-line n/no-sync -- synchronous write needed for log transport reliability appendFileSync(logFilePath, line);