Aethel Bot OSS repository!
aethel.xyz
bot
fun
ai
discord
discord-bot
aethel
1import winston from 'winston';
2import { LOG_LEVEL, NODE_ENV } from '@/config/index';
3import path from 'path';
4
5const sanitizeFormat = winston.format((info) => {
6 const sensitiveKeys = [
7 'password',
8 'token',
9 'api_key',
10 'secret',
11 'authorization',
12 'userid',
13 'user_id',
14 'username',
15 'user_tag',
16 'guildid',
17 'guild_id',
18 'channelid',
19 'channel_id',
20 ];
21
22 const sanitize = (obj: unknown): unknown => {
23 if (typeof obj !== 'object' || obj === null) return obj;
24
25 const sanitized = { ...obj } as Record<string, unknown>;
26 for (const key in sanitized) {
27 if (sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive))) {
28 sanitized[key] = '[REDACTED]';
29 } else if (typeof sanitized[key] === 'string') {
30 sanitized[key] = (sanitized[key] as string).replace(/\b\d{17,19}\b/g, '[ID_REDACTED]');
31 } else if (typeof sanitized[key] === 'object') {
32 sanitized[key] = sanitize(sanitized[key]);
33 }
34 }
35 return sanitized;
36 };
37
38 return sanitize(info) as winston.Logform.TransformableInfo;
39});
40
41const logger = winston.createLogger({
42 level: LOG_LEVEL || 'info',
43 format: winston.format.combine(
44 winston.format.timestamp({
45 format: 'YYYY-MM-DD HH:mm:ss',
46 }),
47 winston.format.errors({ stack: true }),
48 sanitizeFormat(),
49 winston.format.splat(),
50 winston.format.json(),
51 ),
52 defaultMeta: {
53 service: 'Aethel',
54 version: process.env.npm_package_version || '2.0.0',
55 environment: NODE_ENV,
56 },
57 transports: [
58 new winston.transports.Console({
59 format: winston.format.combine(
60 winston.format.colorize(),
61 winston.format.printf(({ timestamp, level, message, service, ...meta }) => {
62 const metaStr = Object.keys(meta).length ? JSON.stringify(meta, null, 2) : '';
63 return `${timestamp} [${service}] ${level}: ${message} ${metaStr}`;
64 }),
65 ),
66 }),
67 ],
68 exitOnError: false,
69});
70
71if (NODE_ENV === 'production') {
72 const logsDir = path.join(process.cwd(), 'logs');
73
74 logger.add(
75 new winston.transports.File({
76 filename: path.join(logsDir, 'error.log'),
77 level: 'error',
78 maxsize: 5242880,
79 maxFiles: 5,
80 format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
81 }),
82 );
83
84 logger.add(
85 new winston.transports.File({
86 filename: path.join(logsDir, 'combined.log'),
87 maxsize: 5242880,
88 maxFiles: 5,
89 format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
90 }),
91 );
92}
93
94logger.exceptions.handle(
95 new winston.transports.Console({
96 format: winston.format.combine(winston.format.colorize(), winston.format.simple()),
97 }),
98);
99
100logger.rejections.handle(
101 new winston.transports.Console({
102 format: winston.format.combine(winston.format.colorize(), winston.format.simple()),
103 }),
104);
105
106export default logger;