/**
* Simple structured logging utility
*/
export enum LogLevel {
DEBUG = 'DEBUG',
INFO = 'INFO',
WARN = 'WARN',
ERROR = 'ERROR',
}
interface LogEntry {
timestamp: string;
level: LogLevel;
message: string;
data?: unknown;
}
class Logger {
private minLevel: LogLevel;
constructor(minLevel: LogLevel = LogLevel.INFO) {
this.minLevel = minLevel;
}
private shouldLog(level: LogLevel): boolean {
const levels = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR];
return levels.indexOf(level) >= levels.indexOf(this.minLevel);
}
private log(level: LogLevel, message: string, data?: unknown): void {
if (!this.shouldLog(level)) {
return;
}
const entry: LogEntry = {
timestamp: new Date().toISOString(),
level,
message,
...(data !== undefined && { data }),
};
const output = JSON.stringify(entry);
switch (level) {
case LogLevel.ERROR:
console.error(output);
break;
case LogLevel.WARN:
console.warn(output);
break;
default:
console.log(output);
}
}
debug(message: string, data?: unknown): void {
this.log(LogLevel.DEBUG, message, data);
}
info(message: string, data?: unknown): void {
this.log(LogLevel.INFO, message, data);
}
warn(message: string, data?: unknown): void {
this.log(LogLevel.WARN, message, data);
}
error(message: string, data?: unknown): void {
this.log(LogLevel.ERROR, message, data);
}
}
// Export singleton instance
export const logger = new Logger(
process.env.LOG_LEVEL === 'DEBUG' ? LogLevel.DEBUG : LogLevel.INFO
);