Skip to main content
Glama
logger.ts4.63 kB
import winston from 'winston'; import util from 'util'; // Define log levels const levels = { error: 0, warn: 1, info: 2, http: 3, debug: 4, }; // Define log level based on environment const level = (): string => { const env = process.env.NODE_ENV || 'development'; return env === 'production' ? 'info' : 'debug'; }; // Define colors for each level const colors = { error: 'red', warn: 'yellow', info: 'green', http: 'magenta', debug: 'blue', }; // Add colors to winston winston.addColors(colors); // Define the format for console output const consoleFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }), winston.format.colorize({ all: true }), winston.format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`), ); // Create a simple filter to reduce unnecessary logs const filterLogs = winston.format((info: winston.Logform.TransformableInfo) => { // Always keep QR code logs (they have the special [WA-QR] prefix) if (typeof info.message === 'string' && info.message.includes('[WA-QR]')) { return info; } // Filter out noisy puppeteer logs if ( typeof info.message === 'string' && // Protocol messages (info.message.includes('puppeteer:protocol') || info.message.includes('SEND') || info.message.includes('RECV') || // Network and WebSocket traffic info.message.includes('Network.') || info.message.includes('webSocket') || // Session and protocol IDs info.message.includes('sessionId') || info.message.includes('targetId') || // General puppeteer noise info.message.includes('puppeteer') || info.message.includes('browser') || info.message.includes('checking') || info.message.includes('polling') || // Protocol payloads and results info.message.includes('payloadData') || info.message.includes('result:{"result"') || // Runtime evaluations info.message.includes('Runtime.') || info.message.includes('execute') || // Common patterns in the logs you showed info.message.includes('method') || info.message.includes('params')) ) { // Filter these out completely regardless of level, except for errors return info.level === 'error' ? info : false; } return info; })(); // Create transports const transports: winston.transport[] = [ // Console transport new winston.transports.Console({ format: winston.format.combine(filterLogs, consoleFormat), stderrLevels: ['error', 'warn'], }), ]; // Create the logger const logger = winston.createLogger({ level: level(), levels, transports, }); // Define types for the logger methods type LogMethod = (message: unknown, ...meta: unknown[]) => winston.Logger; interface LoggerMethods { error: LogMethod; warn: LogMethod; info: LogMethod; http: LogMethod; debug: LogMethod; } // Add a method to log objects with proper formatting const originalLoggers: LoggerMethods = { error: logger.error.bind(logger), warn: logger.warn.bind(logger), info: logger.info.bind(logger), http: logger.http.bind(logger), debug: logger.debug.bind(logger), }; // Override the logger methods to handle objects (Object.keys(originalLoggers) as Array<keyof LoggerMethods>).forEach(level => { logger[level] = function (message: unknown, ...meta: unknown[]): winston.Logger { // If message is an object, format it if (typeof message === 'object' && message !== null) { message = util.inspect(message, { depth: 4, colors: false }); } // If there are additional arguments, format them if (meta.length > 0) { const formattedMeta = meta.map(item => { if (typeof item === 'object' && item !== null) { return util.inspect(item, { depth: 4, colors: false }); } return item; }); return originalLoggers[level].call(logger, `${message} ${formattedMeta.join(' ')}`); } return originalLoggers[level].call(logger, message); }; }); /** * Configure the logger for MCP command mode * In command mode, all logs should go to stderr */ export function configureForCommandMode(): void { // Remove existing console transport logger.transports.forEach(transport => { if (transport instanceof winston.transports.Console) { logger.remove(transport); } }); // Add new console transport that sends everything to stderr logger.add( new winston.transports.Console({ format: winston.format.combine(filterLogs, consoleFormat), stderrLevels: Object.keys(levels), }), ); } export default logger;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fyimail/whatsapp-mcp2'

If you have feedback or need assistance with the MCP directory API, please join our Discord server