Team Ai
Apppublic

LetsTryGPT/agent4-implementation

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
logger.ts230 linesDownload Raw Back to utils
1/**2 * Centralized logging utility3 * Replaces scattered console.log/error/warn statements4 * Provides structured logging with levels and metadata5 */6 7export enum LogLevel {8  DEBUG = 0,9  INFO = 1,10  WARN = 2,11  ERROR = 3,12  NONE = 4,13}14 15export interface LogMeta {16  [key: string]: unknown;17}18 19export interface LogEntry {20  level: keyof typeof LogLevel;21  message: string;22  timestamp: string;23  meta?: LogMeta;24  error?: {25    message: string;26    stack?: string;27    name?: string;28  };29}30 31export class Logger {32  private static instance: Logger;33  private logLevel: LogLevel;34  private enableConsole: boolean;35  private logs: LogEntry[] = [];36 37  private constructor(logLevel: LogLevel = LogLevel.INFO, enableConsole: boolean = true) {38    this.logLevel = logLevel;39    this.enableConsole = enableConsole;40  }41 42  /**43   * Get singleton logger instance44   */45  static getInstance(): Logger {46    if (!Logger.instance) {47      // Read log level from env48      const levelStr = process.env.LOG_LEVEL || 'info';49      const level = Logger.parseLogLevel(levelStr);50      Logger.instance = new Logger(level, process.env.NODE_ENV !== 'test');51    }52    return Logger.instance;53  }54 55  /**56   * Parse log level from string57   */58  private static parseLogLevel(level: string): LogLevel {59    const normalized = level.toUpperCase();60    if (normalized in LogLevel) {61      return LogLevel[normalized as keyof typeof LogLevel];62    }63    return LogLevel.INFO;64  }65 66  /**67   * Set log level68   */69  setLogLevel(level: LogLevel): void {70    this.logLevel = level;71  }72 73  /**74   * Enable/disable console output75   */76  setConsoleOutput(enabled: boolean): void {77    this.enableConsole = enabled;78  }79 80  /**81   * Create log entry82   */83  private createEntry(84    level: keyof typeof LogLevel,85    message: string,86    meta?: LogMeta,87    error?: Error88  ): LogEntry {89    const entry: LogEntry = {90      level,91      message,92      timestamp: new Date().toISOString(),93    };94 95    if (meta) {96      entry.meta = meta;97    }98 99    if (error) {100      entry.error = {101        message: error.message,102        name: error.name,103        stack: error.stack,104      };105    }106 107    return entry;108  }109 110  /**111   * Write log entry112   */113  private write(entry: LogEntry): void {114    const levelValue = LogLevel[entry.level];115 116    if (levelValue < this.logLevel) {117      return; // Skip if below configured log level118    }119 120    // Store in memory (circular buffer, keep last 1000)121    this.logs.push(entry);122    if (this.logs.length > 1000) {123      this.logs.shift();124    }125 126    // Output to console if enabled127    if (this.enableConsole) {128      this.outputToConsole(entry);129    }130  }131 132  /**133   * Output log entry to console134   */135  private outputToConsole(entry: LogEntry): void {136    const prefix = `[${entry.timestamp}] [${entry.level}]`;137    const message = `${prefix} ${entry.message}`;138 139    switch (entry.level) {140      case 'DEBUG':141      case 'INFO':142        console.log(message, entry.meta || '');143        break;144      case 'WARN':145        console.warn(message, entry.meta || '');146        break;147      case 'ERROR':148        console.error(message, entry.error || entry.meta || '');149        if (entry.error?.stack) {150          console.error(entry.error.stack);151        }152        break;153    }154  }155 156  /**157   * Debug level logging158   */159  debug(message: string, meta?: LogMeta): void {160    this.write(this.createEntry('DEBUG', message, meta));161  }162 163  /**164   * Info level logging165   */166  info(message: string, meta?: LogMeta): void {167    this.write(this.createEntry('INFO', message, meta));168  }169 170  /**171   * Warning level logging172   */173  warn(message: string, meta?: LogMeta): void {174    this.write(this.createEntry('WARN', message, meta));175  }176 177  /**178   * Error level logging179   */180  error(message: string, error?: Error, meta?: LogMeta): void {181    this.write(this.createEntry('ERROR', message, meta, error));182  }183 184  /**185   * Get recent logs186   */187  getRecentLogs(count: number = 100): LogEntry[] {188    return this.logs.slice(-count);189  }190 191  /**192   * Clear logs193   */194  clearLogs(): void {195    this.logs = [];196  }197 198  /**199   * Get logs matching criteria200   */201  getLogs(filter?: { level?: keyof typeof LogLevel; since?: Date }): LogEntry[] {202    let filtered = [...this.logs];203 204    if (filter?.level) {205      filtered = filtered.filter((log) => log.level === filter.level);206    }207 208    if (filter?.since) {209      const sinceTime = filter.since.getTime();210      filtered = filtered.filter((log) => new Date(log.timestamp).getTime() >= sinceTime);211    }212 213    return filtered;214  }215}216 217/**218 * Export convenience instance219 */220export const logger = Logger.getInstance();221 222/**223 * Convenience functions224 */225export const debug = (message: string, meta?: LogMeta) => logger.debug(message, meta);226export const info = (message: string, meta?: LogMeta) => logger.info(message, meta);227export const warn = (message: string, meta?: LogMeta) => logger.warn(message, meta);228export const error = (message: string, err?: Error, meta?: LogMeta) =>229  logger.error(message, err, meta);230