Skip to main content
Glama
logger.ts3.04 kB
import winston from 'winston'; import path from 'path'; import fs from 'fs'; import 'winston-daily-rotate-file'; import os from 'os'; import archiver from 'archiver'; // Get platform-specific app data directory function getAppDataDir(): string { const platform = process.platform; const appName = 'rednote-mcp'; switch (platform) { case 'win32': // Windows: %APPDATA%\rednote-mcp\logs return path.join(process.env.APPDATA || '', appName, 'logs'); case 'darwin': // macOS: ~/Library/Application Support/rednote-mcp/logs return path.join(os.homedir(), 'Library', 'Application Support', appName, 'logs'); case 'linux': // Linux: ~/.local/share/rednote-mcp/logs return path.join(os.homedir(), '.local', 'share', appName, 'logs'); default: // Fallback to current directory if platform is not recognized return path.join(process.cwd(), 'logs'); } } // Constants for log management export const LOGS_DIR = getAppDataDir(); const MAX_LOG_SIZE = 10 * 1024 * 1024; // 10MB const MAX_LOG_FILES = 5; // Keep last 5 log files // Create logs directory if it doesn't exist if (!fs.existsSync(LOGS_DIR)) { fs.mkdirSync(LOGS_DIR, { recursive: true }); } // Configure logger const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ // Write all logs with level 'error' and below to error.log new winston.transports.DailyRotateFile({ filename: path.join(LOGS_DIR, 'error-%DATE%.log'), datePattern: 'YYYY-MM-DD', maxSize: MAX_LOG_SIZE, maxFiles: MAX_LOG_FILES, level: 'error', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ) }), // Write all logs with level 'info' and below to combined.log new winston.transports.DailyRotateFile({ filename: path.join(LOGS_DIR, 'combined-%DATE%.log'), datePattern: 'YYYY-MM-DD', maxSize: MAX_LOG_SIZE, maxFiles: MAX_LOG_FILES, format: winston.format.combine( winston.format.timestamp(), winston.format.json() ) }) ] }); // Add a stream for Morgan (if needed in the future) export const stream = { write: (message: string) => { logger.info(message.trim()); } }; // Function to pack logs into a zip file export async function packLogs(): Promise<string> { const output = fs.createWriteStream(path.join(process.cwd(), 'rednote-logs.zip')); const archive = archiver('zip', { zlib: { level: 9 } // Sets the compression level }); return new Promise((resolve, reject) => { output.on('close', () => { resolve(path.join(process.cwd(), 'rednote-logs.zip')); }); archive.on('error', (err: Error) => { reject(err); }); archive.pipe(output); // Add all log files to the archive if (fs.existsSync(LOGS_DIR)) { archive.directory(LOGS_DIR, 'logs'); } archive.finalize(); }); } 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/JonaFly/RedNote-MCP'

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