/**
* Structured JSON Logger
* Outputs JSON lines for observability in Lambda / CloudWatch / local dev.
*/
const LOG_LEVELS = {
debug: 0,
info: 1,
warn: 2,
error: 3,
} as const;
type LogLevel = keyof typeof LOG_LEVELS;
interface LoggerOptions {
level: string;
service: string;
}
export class Logger {
private readonly level: LogLevel;
private readonly service: string;
constructor(options: LoggerOptions) {
const parsed = options.level.toLowerCase();
this.level = parsed in LOG_LEVELS ? (parsed as LogLevel) : 'info';
this.service = options.service;
}
debug(message: string, meta?: Record<string, unknown>): void {
this.log('debug', message, meta);
}
info(message: string, meta?: Record<string, unknown>): void {
this.log('info', message, meta);
}
warn(message: string, meta?: Record<string, unknown>): void {
this.log('warn', message, meta);
}
error(message: string, meta?: Record<string, unknown>): void {
this.log('error', message, meta);
}
private log(level: LogLevel, message: string, meta?: Record<string, unknown>): void {
if (LOG_LEVELS[level] < LOG_LEVELS[this.level]) {
return;
}
const entry = {
timestamp: new Date().toISOString(),
level,
service: this.service,
message,
...meta,
};
const output = level === 'error' || level === 'warn'
? process.stderr
: process.stdout;
output.write(JSON.stringify(entry) + '\n');
}
}
/** Default logger instance for the gateway. */
export const logger = new Logger({
level: process.env['LOG_LEVEL'] ?? 'info',
service: 'shopify-agentic-mcp',
});