diff options
Diffstat (limited to 'src/logging.ts')
| -rw-r--r-- | src/logging.ts | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/logging.ts b/src/logging.ts new file mode 100644 index 0000000..e7b26f2 --- /dev/null +++ b/src/logging.ts @@ -0,0 +1,69 @@ +/** + * Structured, level-filtered logging for the service's own messages. + * + * matter.js library logging is configured separately (see controller.ts); this + * logger covers service-level events in the format: + * + * 2026-07-26T20:00:00.100Z INFO controller Connected to Matter node 1 + */ + +export const LOG_LEVELS = ["debug", "info", "warn", "error"] as const; +export type LogLevel = (typeof LOG_LEVELS)[number]; + +export function isLogLevel(value: unknown): value is LogLevel { + return typeof value === "string" && (LOG_LEVELS as readonly string[]).includes(value); +} + +const LEVEL_RANK: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 }; +const LEVEL_LABEL: Record<LogLevel, string> = { + debug: "DEBUG", + info: "INFO ", + warn: "WARN ", + error: "ERROR", +}; + +let globalLevel: LogLevel = "info"; + +export function setLogLevel(level: LogLevel): void { + globalLevel = level; +} + +export function getLogLevel(): LogLevel { + return globalLevel; +} + +function write(level: LogLevel, module: string, message: string): void { + if (LEVEL_RANK[level] < LEVEL_RANK[globalLevel]) return; + const line = `${new Date().toISOString()} ${LEVEL_LABEL[level]} ${module} ${message}`; + // All log levels go to stderr: stdout is reserved for command output so + // that --json (and any piped human output) is never interleaved with logs. + process.stderr.write(line + "\n"); +} + +/** A logger bound to a module name (e.g. "controller", "sync"). */ +export class Log { + constructor(private readonly module: string) {} + + debug(message: string): void { + write("debug", this.module, message); + } + + info(message: string): void { + write("info", this.module, message); + } + + warn(message: string): void { + write("warn", this.module, message); + } + + error(message: string, cause?: unknown): void { + write("error", this.module, cause === undefined ? message : `${message}: ${describeError(cause)}`); + } +} + +export function describeError(cause: unknown): string { + if (cause instanceof Error) { + return cause.message; + } + return String(cause); +} |
