llmxml
Version:
Convert between markdown and LLM-friendly pseudo-XML
111 lines (101 loc) • 2.96 kB
text/typescript
import winston from 'winston';
import { EventEmitter } from 'events';
import type { Warning } from '../types';
/**
* Event emitter for library-level events
*/
export const events = new EventEmitter();
/**
* Custom transport that emits events for warnings
*/
class EventTransport extends winston.transports.Stream {
constructor(opts?: any) {
super({
stream: process.stdout,
...opts
});
// @ts-ignore - winston types are incorrect, eol can be boolean
this.eol = true;
this.level = 'warn';
}
log(info: any, callback: () => void) {
setImmediate(() => {
this.emit('logged', info);
});
// Extract the message and metadata
const { message, level, timestamp, ...meta } = info;
// Emit the warning event with our format
if (level === 'warn') {
events.emit('warning', {
code: meta.code || 'UNKNOWN_WARNING',
message: message,
details: meta
} as Warning);
}
callback();
}
}
/**
* Centralized logger for the LLMXML library
*
* In development:
* - Logs to console with colors and simple format
*
* In production:
* - Logs errors to error.log
* - Logs all levels to combined.log
* - Uses JSON format with timestamps
*
* Respects LLMXML options:
* - When warningLevel is 'none', only errors are logged
* - When verbose is false, initialization logs are suppressed
*/
const logger = winston.createLogger({
/** Set by LOG_LEVEL env var or defaults to 'info' */
level: process.env.LOG_LEVEL || 'info',
/** Use JSON format with timestamps for structured logging */
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
/** Console output with colors in development */
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
}),
/** Event transport for warning events */
new EventTransport(),
],
});
// Add file transports in production
if (process.env.NODE_ENV === 'production') {
/** Log errors to dedicated file */
logger.add(
new winston.transports.File({ filename: 'error.log', level: 'error' })
);
/** Log all levels to combined file */
logger.add(
new winston.transports.File({ filename: 'combined.log' })
);
}
/**
* Updates logger level based on LLMXML options
* @param options Options from LLMXML instance
*/
export function configureLogger(options: { warningLevel?: 'all' | 'none' | 'ambiguous-only', verbose?: boolean } = {}) {
// Set log level based on warningLevel
if (options.warningLevel === 'none') {
// When warningLevel is 'none', only log errors
logger.level = 'error';
} else if (!options.verbose) {
// When not verbose, don't show info logs
logger.level = 'warn';
} else {
// Default to info level
logger.level = process.env.LOG_LEVEL || 'info';
}
}
export default logger;