112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import { createLogger, format, transports } from 'winston';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
// Create logs directory if it doesn't exist
|
|
const logsDir = path.join(process.cwd(), 'logs');
|
|
if (!fs.existsSync(logsDir)) {
|
|
fs.mkdirSync(logsDir);
|
|
}
|
|
|
|
// Define colors for different service types
|
|
const colors: any = {
|
|
error: '\x1b[31m', // red
|
|
warn: '\x1b[33m', // yellow
|
|
info: '\x1b[32m', // green
|
|
debug: '\x1b[36m', // cyan
|
|
reset: '\x1b[0m', // reset
|
|
|
|
// Service specific colors
|
|
IPFS: '\x1b[36m', // cyan
|
|
HEARTBEAT: '\x1b[33m', // yellow
|
|
SOCKET: '\x1b[34m', // blue
|
|
'LOAD-BALANCER': '\x1b[35m', // magenta
|
|
DEFAULT: '\x1b[37m', // white
|
|
};
|
|
|
|
// Custom format for console output with colors
|
|
const customConsoleFormat = format.printf(({ level, message, timestamp, service }: any) => {
|
|
// Truncate error messages
|
|
if (level === 'error' && typeof message === 'string' && message.length > 300) {
|
|
message = message.substring(0, 300) + '... [truncated]';
|
|
}
|
|
|
|
// Handle objects and errors
|
|
if (typeof message === 'object' && message !== null) {
|
|
if (message instanceof Error) {
|
|
message = message.message;
|
|
// Truncate error messages
|
|
if (message.length > 300) {
|
|
message = message.substring(0, 300) + '... [truncated]';
|
|
}
|
|
} else {
|
|
try {
|
|
message = JSON.stringify(message, null, 2);
|
|
} catch (_e) {
|
|
message = '[Object]';
|
|
}
|
|
}
|
|
}
|
|
|
|
const serviceColor = service && colors[service] ? colors[service] : colors.DEFAULT;
|
|
const levelColor = colors[level] || colors.DEFAULT;
|
|
const serviceTag = service ? `[${service}]` : '';
|
|
|
|
return `${timestamp} ${levelColor}${level}${colors.reset}: ${serviceColor}${serviceTag}${colors.reset} ${message}`;
|
|
});
|
|
|
|
// Custom format for file output (no colors)
|
|
const customFileFormat = format.printf(({ level, message, timestamp, service }) => {
|
|
// Handle objects and errors
|
|
if (typeof message === 'object' && message !== null) {
|
|
if (message instanceof Error) {
|
|
message = message.message;
|
|
} else {
|
|
try {
|
|
message = JSON.stringify(message);
|
|
} catch (_e) {
|
|
message = '[Object]';
|
|
}
|
|
}
|
|
}
|
|
|
|
const serviceTag = service ? `[${service}]` : '';
|
|
return `${timestamp} ${level}: ${serviceTag} ${message}`;
|
|
});
|
|
|
|
// Create the logger
|
|
const logger = createLogger({
|
|
level: process.env.LOG_LEVEL || 'info',
|
|
format: format.combine(format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.splat()),
|
|
defaultMeta: { service: 'DEFAULT' },
|
|
transports: [
|
|
// Console transport
|
|
new transports.Console({
|
|
format: format.combine(format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customConsoleFormat),
|
|
}),
|
|
// Combined log file
|
|
new transports.File({
|
|
filename: path.join(logsDir, 'app.log'),
|
|
format: format.combine(format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customFileFormat),
|
|
}),
|
|
// Error log file
|
|
new transports.File({
|
|
filename: path.join(logsDir, 'error.log'),
|
|
level: 'error',
|
|
format: format.combine(format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customFileFormat),
|
|
}),
|
|
],
|
|
});
|
|
|
|
// Helper function to create a logger for a specific service
|
|
export const createServiceLogger = (serviceName: string) => {
|
|
return {
|
|
error: (message: any, ...meta: any[]) => logger.error(message, { service: serviceName, ...meta }),
|
|
warn: (message: any, ...meta: any[]) => logger.warn(message, { service: serviceName, ...meta }),
|
|
info: (message: any, ...meta: any[]) => logger.info(message, { service: serviceName, ...meta }),
|
|
debug: (message: any, ...meta: any[]) => logger.debug(message, { service: serviceName, ...meta }),
|
|
};
|
|
};
|
|
|
|
export default logger;
|