logger.ts•1.94 kB
export enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
}
export class Logger {
private static instance: Logger;
private logLevel: LogLevel = LogLevel.INFO;
private isProduction: boolean = false;
private constructor() {
// Check if running in production (when used as MCP server)
this.isProduction =
process.env.NODE_ENV === "production" ||
process.env.MCP_PRODUCTION === "true" ||
!process.stdout.isTTY;
}
static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
setLogLevel(level: LogLevel): void {
this.logLevel = level;
}
private log(level: LogLevel, message: string, ...args: unknown[]): void {
if (level < this.logLevel) {
return;
}
// In production, only log errors and warnings to avoid noise
if (this.isProduction && level < LogLevel.WARN) {
return;
}
const timestamp = new Date().toISOString();
const levelName = LogLevel[level];
const prefix = `[${timestamp}] [${levelName}]`;
switch (level) {
case LogLevel.DEBUG:
console.debug(prefix, message, ...args);
break;
case LogLevel.INFO:
console.info(prefix, message, ...args);
break;
case LogLevel.WARN:
console.warn(prefix, message, ...args);
break;
case LogLevel.ERROR:
console.error(prefix, message, ...args);
break;
}
}
debug(message: string, ...args: unknown[]): void {
this.log(LogLevel.DEBUG, message, ...args);
}
info(message: string, ...args: unknown[]): void {
this.log(LogLevel.INFO, message, ...args);
}
warn(message: string, ...args: unknown[]): void {
this.log(LogLevel.WARN, message, ...args);
}
error(message: string, ...args: unknown[]): void {
this.log(LogLevel.ERROR, message, ...args);
}
}
export const logger = Logger.getInstance();