import { createRequire } from 'node:module';
import type { Logger as PinoLogger } from 'pino';
import { env } from './config/env.js';
type LogFields = Record<string, unknown>;
type LogMethod = {
(message: string, ...args: unknown[]): void;
(fields: LogFields, message?: string): void;
};
export interface AppLogger {
debug: LogMethod;
info: LogMethod;
warn: LogMethod;
error: LogMethod;
}
const adaptMethod = (method: (...args: unknown[]) => unknown): LogMethod => {
return ((first: unknown, ...rest: unknown[]) => {
if (typeof first === 'string' || first instanceof Error) {
method(first, ...rest);
return;
}
method(first as LogFields, ...rest);
}) as LogMethod;
};
const createConsoleLogger = (): AppLogger => {
const log = (level: 'debug' | 'info' | 'warn' | 'error', first: unknown, ...rest: unknown[]) => {
const prefix = `[${level}]`;
if (typeof first === 'string') {
console[level](prefix, first, ...rest);
return;
}
console[level](prefix, first, ...rest);
};
const wrap = (level: 'debug' | 'info' | 'warn' | 'error'): LogMethod =>
((first: unknown, ...rest: unknown[]) => {
log(level, first, ...rest);
}) as LogMethod;
return {
debug: wrap('debug'),
info: wrap('info'),
warn: wrap('warn'),
error: wrap('error'),
};
};
const createPinoLogger = (pinoLogger: PinoLogger): AppLogger => ({
debug: adaptMethod(pinoLogger.debug.bind(pinoLogger)),
info: adaptMethod(pinoLogger.info.bind(pinoLogger)),
warn: adaptMethod(pinoLogger.warn.bind(pinoLogger)),
error: adaptMethod(pinoLogger.error.bind(pinoLogger)),
});
const initializeLogger = (): AppLogger => {
try {
const require = createRequire(import.meta.url);
const pino = require('pino') as typeof import('pino');
const base = pino({
name: env.MCP_SERVER_NAME,
level: env.LOG_LEVEL,
transport:
env.NODE_ENV === 'development'
? {
target: 'pino-pretty',
options: {
translateTime: 'SYS:standard',
ignore: 'pid,hostname',
},
}
: undefined,
});
return createPinoLogger(base);
} catch (error) {
const reason = error instanceof Error ? error.message : String(error);
console.warn(`Pino logger unavailable (${reason}); falling back to console logger.`);
return createConsoleLogger();
}
};
export const logger: AppLogger = initializeLogger();