export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; export interface LogEntry { level: LogLevel; msg: string; time: number; [key: string]: unknown; } export interface LoggerOptions { level?: LogLevel; name?: string; base?: Record; transport?: (entry: LogEntry) => void; } export interface KittenLogger { trace(msg: string, data?: Record): void; debug(msg: string, data?: Record): void; info(msg: string, data?: Record): void; warn(msg: string, data?: Record): void; error(msg: string, data?: Record): void; fatal(msg: string, data?: Record): void; child(bindings: Record): KittenLogger; } const LEVELS: Record = { trace: 10, debug: 20, info: 30, warn: 40, error: 50, fatal: 60, }; const defaultTransport = (entry: LogEntry) => { const out = JSON.stringify(entry); if (entry.level === "error" || entry.level === "fatal") console.error(out); else console.log(out); }; export class Logger implements KittenLogger { private readonly minLevel: number; private readonly base: Record; private readonly transport: (entry: LogEntry) => void; constructor(private readonly options: LoggerOptions = {}) { this.minLevel = LEVELS[options.level ?? "info"]; this.base = { ...(options.name ? { name: options.name } : {}), ...options.base, }; this.transport = options.transport ?? defaultTransport; } private write(level: LogLevel, msg: string, data?: Record) { if (LEVELS[level] < this.minLevel) return; this.transport({ level, msg, time: Date.now(), ...this.base, ...data, }); } trace(msg: string, data?: Record) { this.write("trace", msg, data); } debug(msg: string, data?: Record) { this.write("debug", msg, data); } info(msg: string, data?: Record) { this.write("info", msg, data); } warn(msg: string, data?: Record) { this.write("warn", msg, data); } error(msg: string, data?: Record) { this.write("error", msg, data); } fatal(msg: string, data?: Record) { this.write("fatal", msg, data); } child(bindings: Record): KittenLogger { return new Logger({ ...this.options, base: { ...this.base, ...bindings }, }); } } const baseLogger = new Logger(); export { baseLogger };