type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'; interface LogContext { requestId?: string; userId?: string; traceId?: string; [key: string]: unknown; } interface LogEntry { level: LogLevel; message: string; timestamp: string; context: LogContext; error?: SerializedError; data?: Record; } interface SerializedError { name: string; message: string; stack: string | undefined; code: string | number | undefined; } interface Transport { write(entry: LogEntry): void; } interface SmartLoggerOptions { /** Minimum log level to output (default: 'info') */ level?: LogLevel; /** Service/app name added to every log entry */ serviceName?: string; /** Custom transports (default: console JSON transport) */ transports?: Transport[]; /** * Fields to automatically redact from log output. * Values are replaced with '[REDACTED]'. * Default: ['password', 'token', 'secret', 'authorization', 'cookie', 'apiKey', 'api_key'] */ redactFields?: string[]; /** Pretty-print logs (useful in development, never in production) */ prettyPrint?: boolean; } /** * SmartLogger — structured, context-aware logging for Node.js backends. * * Key features: * - **Async context propagation**: request ID automatically flows through * all async calls without manual passing — powered by AsyncLocalStorage. * - **Automatic redaction**: sensitive fields (passwords, tokens, etc.) are * replaced with '[REDACTED]' before writing to any transport. * - **Structured JSON output**: machine-parseable logs, OpenTelemetry-ready. * - **Child loggers**: create scoped loggers that inherit parent context. * * @example * const logger = new SmartLogger({ serviceName: 'api', level: 'info' }); * * // In Express middleware: * app.use((req, res, next) => { * logger.runWithContext({ requestId: req.headers['x-request-id'] ?? randomUUID() }, next); * }); * * // Anywhere in the async call chain: * logger.info('User created', { userId: '123' }); * // → {"level":"info","message":"User created","context":{"requestId":"abc-123"},"data":{"userId":"123"}} */ declare class SmartLogger { private readonly level; private readonly serviceName; private readonly transports; private readonly redactFields; private readonly storage; private readonly baseContext; constructor(options?: SmartLoggerOptions); /** * Run `fn` with the given context available to all nested async calls. * Use this in middleware to inject requestId, userId, traceId, etc. */ runWithContext(context: LogContext, fn: () => T): T; /** * Generate a new requestId and run `fn` within that context. * Convenience wrapper for runWithContext. */ withRequestId(fn: () => T, extraContext?: LogContext): T; /** Get the context bound to the current async scope */ get currentContext(): LogContext; debug(message: string, data?: Record): void; info(message: string, data?: Record): void; warn(message: string, data?: Record): void; error(message: string, error?: unknown, data?: Record): void; /** * Create a child logger that merges `context` into every log entry. * The child shares the parent's transports and settings. * * @example * const reqLogger = logger.child({ requestId: req.id, userId: req.user.id }); * reqLogger.info('Payment started'); // includes requestId + userId automatically */ child(context: LogContext): SmartLogger; private write; private redact; private serializeError; } /** * Minimal Express-compatible types — avoids hard dependency on @types/express. */ interface Request { headers: Record; method: string; url: string; [key: string]: unknown; } interface Response { statusCode: number; on(event: string, listener: () => void): void; setHeader(name: string, value: string): void; [key: string]: unknown; } type NextFunction = () => void; /** * Express middleware that: * 1. Attaches a requestId to every incoming request (from header or generated). * 2. Runs the rest of the chain inside a logging context — so every log * call inside a request handler automatically includes the requestId. * 3. Logs request start and completion with duration. * * @example * import express from 'express'; * import { SmartLogger } from 'rezilia/logger'; * import { requestLogger } from 'rezilia/logger/middleware/express'; * * const app = express(); * const logger = new SmartLogger({ serviceName: 'api' }); * app.use(requestLogger(logger)); */ declare function requestLogger(logger: SmartLogger): (req: Request, res: Response, next: NextFunction) => void; export { type LogContext, type LogEntry, type LogLevel, type SerializedError, SmartLogger, type SmartLoggerOptions, type Transport, requestLogger };