UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

124 lines (116 loc) 3.3 kB
/** * Supported structured logger levels. */ export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; /** * App-facing structured logger port. * * Application code logs through this interface so production can use Pino, * Datadog, or another adapter while tests can use no-op or memory loggers. */ export interface LoggerPort { /** * Log very detailed diagnostic information. */ trace(message: string, meta?: Record<string, unknown>): void; /** * Log debug-level diagnostic information. */ debug(message: string, meta?: Record<string, unknown>): void; /** * Log normal application progress. */ info(message: string, meta?: Record<string, unknown>): void; /** * Log recoverable problems or unusual conditions. */ warn(message: string, meta?: Record<string, unknown>): void; /** * Log failed operations. */ error(message: string, meta?: Record<string, unknown>): void; /** * Log unrecoverable failures. */ fatal(message: string, meta?: Record<string, unknown>): void; /** * Return a logger with additional structured bindings. */ child(bindings: Record<string, unknown>): LoggerPort; } /** * Captured entry from `createMemoryLogger(...)`. */ export interface MemoryLogEntry { level: LogLevel; message: string; meta?: Record<string, unknown>; bindings: Record<string, unknown>; } /** * In-memory logger port used by tests and local assertions. */ export interface MemoryLoggerPort extends LoggerPort { /** * Captured log entries in call order. */ entries: MemoryLogEntry[]; } /** * Create a logger that discards every log call. * * Use this in tests where logging is irrelevant. * * @returns A logger port whose methods are no-ops. */ export function createNoopLogger(): LoggerPort { const logger: LoggerPort = { trace: () => {}, debug: () => {}, info: () => {}, warn: () => {}, error: () => {}, fatal: () => {}, child: () => logger, }; return logger; } /** * Create a logger that captures entries in memory. * * Child loggers inherit existing bindings and append new bindings to each * captured entry. * * @param bindings - Structured bindings attached to every captured entry. * @param entries - Optional shared entry array. * @returns A logger port with an inspectable `entries` array. */ export function createMemoryLogger( bindings: Record<string, unknown> = {}, entries: MemoryLogEntry[] = [], ): MemoryLoggerPort { const capturedBindings = { ...bindings }; const record = ( level: LogLevel, message: string, meta?: Record<string, unknown>, ) => { entries.push({ level, message, meta: meta ? { ...meta } : undefined, bindings: { ...capturedBindings }, }); }; return { entries, trace: (message, meta) => record("trace", message, meta), debug: (message, meta) => record("debug", message, meta), info: (message, meta) => record("info", message, meta), warn: (message, meta) => record("warn", message, meta), error: (message, meta) => record("error", message, meta), fatal: (message, meta) => record("fatal", message, meta), child: (childBindings) => createMemoryLogger({ ...capturedBindings, ...childBindings }, entries), }; }