export type LogLevel = 'error' | 'warn' | 'info' | 'debug'; export interface LogEntry { timestamp: string; level: LogLevel; message: string; context?: Record; stack?: string; requestId?: string; userId?: string; component?: string; } export interface LoggerOptions { component?: string; requestId?: string; userId?: string; } export declare class LoggerService { private static instance; private config; private logQueue; private flushTimer; private isShuttingDown; private readonly LOG_LEVELS; private constructor(); static getInstance(): LoggerService; private getLoggingConfig; private initializeLogDirectory; private startLogFlusher; /** * Register process-level hooks that keep the file log complete. * * A stop signal is NOT the end of the process: since the safe-restart * change the backend drains in-flight agent turns for up to 120s after * SIGTERM, then runs its graceful shutdown. Stopping the flusher on the * signal (the old behaviour) dropped that whole window — "Received * SIGTERM", the drain, "Server shut down gracefully" — from the daily log, * so no restart on 2026-09-24 showed its cause there. On a signal we only * flush what is queued and keep the periodic flusher running; the queue is * drained synchronously on 'exit', where async writes never complete. */ private setupProcessHandlers; private shouldLog; /** * One log line. Crewly Apps open-link tokens are redacted from every line, * whatever logged them (specs/2026-10-04-crewly-apps-p3.md §1). */ private formatLogEntry; private formatLogEntryRaw; private writeToFile; private rotateLogs; private log; private writeToConsole; private flushLogs; /** * Write every queued entry to today's log file synchronously. * * Used from the process 'exit' handler, where the event loop no longer runs * and an async append would be abandoned. Rotation is skipped here; the next * boot's first async write rotates as usual. Errors are reported to stderr * and never thrown, since throwing inside 'exit' would mask the exit code. */ private flushLogsSync; error(message: string, context?: Record, options?: LoggerOptions): void; warn(message: string, context?: Record, options?: LoggerOptions): void; info(message: string, context?: Record, options?: LoggerOptions): void; debug(message: string, context?: Record, options?: LoggerOptions): void; logHttpRequest(method: string, url: string, statusCode: number, duration: number, options?: LoggerOptions): void; logHttpError(method: string, url: string, statusCode: number, error: string, options?: LoggerOptions): void; logAgentAction(agentId: string, action: string, success: boolean, details?: Record, options?: LoggerOptions): void; logSystemMetric(metric: string, value: number, unit: string, options?: LoggerOptions): void; logSecurityEvent(event: string, details: Record, options?: LoggerOptions): void; logDatabaseOperation(operation: string, table: string, duration: number, success: boolean, options?: LoggerOptions): void; createComponentLogger(component: string): ComponentLogger; createRequestLogger(requestId: string, userId?: string): RequestLogger; getRecentLogs(level?: LogLevel, limit?: number): Promise; /** * Stop the periodic flusher and drain queued file logs. * * Returns the flush promise so callers that can wait (CLI commands) get * their last lines on disk; the process 'exit' handler calls it without * awaiting, which is unchanged behaviour. * * @returns Resolves once the queued entries are written */ shutdown(): Promise; } export declare class ComponentLogger { private logger; private component; constructor(logger: LoggerService, component: string); error(message: string, context?: Record, options?: Omit): void; warn(message: string, context?: Record, options?: Omit): void; info(message: string, context?: Record, options?: Omit): void; debug(message: string, context?: Record, options?: Omit): void; } export declare class RequestLogger { private logger; private requestId; private userId?; constructor(logger: LoggerService, requestId: string, userId?: string | undefined); error(message: string, context?: Record, options?: Omit): void; warn(message: string, context?: Record, options?: Omit): void; info(message: string, context?: Record, options?: Omit): void; debug(message: string, context?: Record, options?: Omit): void; } //# sourceMappingURL=logger.service.d.ts.map