cmte
Version:
Design by Committee™ except it's just you and LLMs
87 lines (72 loc) • 2.75 kB
JavaScript
import winston from 'winston';
import path from 'path';
import fs from 'fs';
// Ensure logs directory exists
const logsDir = path.join(process.cwd(), 'logs');
if (!fs.existsSync(logsDir)) {
fs.mkdirSync(logsDir);
}
// Default console format
const consoleFormat = winston.format.combine(
winston.format.colorize(),
winston.format.printf(({ level, message }) => `${level}: ${message}`)
);
// Default file format
const fileFormat = winston.format.combine(
winston.format.timestamp(),
winston.format.json()
);
// Create a basic logger instance initially (might be used before configure is called)
// It will only log to console by default until configured.
const logger = winston.createLogger({
level: 'info', // Default level before configuration
format: winston.format.json(), // Default format
transports: [
new winston.transports.Console({
format: consoleFormat,
level: 'info' // Default console level
})
],
exitOnError: false
});
// --- Configuration Function ---
let isConfigured = false;
function configureLogger(options = {}) {
// Prevent multiple configurations in the same process
if (isConfigured) {
logger.debug('Logger already configured. Skipping reconfiguration.');
return;
}
const { debug = false, dryrun = false } = options;
// Determine levels based on debug flag AND dryrun
const consoleLevel = debug ? 'debug' : (dryrun ? 'warn' : 'info'); // Console: warn for dryrun, info otherwise, debug overrides
const fileLevel = debug ? 'debug' : 'warn'; // File: Still warn/error by default, debug if requested
// Generate timestamped filename (only once per process)
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const logFilename = path.join(logsDir, `cmte-${timestamp}.log`);
// Clear existing transports before adding configured ones
logger.clear();
// Add Console Transport
logger.add(new winston.transports.Console({
format: consoleFormat,
level: consoleLevel
}));
// Add File Transport
logger.add(new winston.transports.File({
filename: logFilename,
format: fileFormat,
level: fileLevel // Set level based on debug flag
}));
// Update the logger's overall level (only needs to be debug if debug is enabled)
if (debug) {
logger.level = 'debug';
// logger.info('Console logging enabled (Level: debug)'); // Already logged when transport added
} else {
// Ensure level is at least info for console or warn for file if not debugging
logger.level = dryrun ? 'warn' : 'info';
}
isConfigured = true;
logger.debug('Logger configured', { consoleLevel, fileLevel, logFilename });
}
// Export the configure function and the logger instance
export { logger, configureLogger };