diff --git a/apis/websocket/config.schema.json b/apis/websocket/config.schema.json index 42e1214..be812b1 100755 --- a/apis/websocket/config.schema.json +++ b/apis/websocket/config.schema.json @@ -25,7 +25,7 @@ "consoleLogLevel": { "description": "The log level to print to console", "type": "string", - "enum": ["error", "warn", "info", "verbose", "debug", "silly", "none"], + "enum": ["error", "warn", "info", "log", "debug", "none"], "default": "info" } } diff --git a/apis/websocket/docs/1_configuration.md b/apis/websocket/docs/1_configuration.md index 5f2454b..1cc2d5e 100644 --- a/apis/websocket/docs/1_configuration.md +++ b/apis/websocket/docs/1_configuration.md @@ -28,9 +28,18 @@ Amount of concurrent queues that can be run at a time. Heartbeat interval for clients. See [**💓 Heartbeating**](./packets.md#💓-heartbeating). -### `config.debugLogsInProduction` +### `config.consoleLogLevel` -Whether to print debug logs at all in production mode (when `NODE_ENV` is `production`). +The level of logs to print to console. If the level is more important or equally important to set level, it will be forwarded to the console. + +The possible levels (sorted by their importance descendingly) are: +- `fatal` +- `error` +- `warn` +- `info` +- `log` +- `trace` +- `debug` ## ⏭️ What's next diff --git a/apis/websocket/src/index.ts b/apis/websocket/src/index.ts index d04bdfc..d5e287a 100755 --- a/apis/websocket/src/index.ts +++ b/apis/websocket/src/index.ts @@ -18,9 +18,8 @@ import { checkEnvironment, getConfig } from './utils/index.js' // Load config, init logger, check environment const config = getConfig() -const logger = createLogger('websocket-api', { - level: config.consoleLogLevel === 'none' ? 'error' : config.consoleLogLevel, - silent: config.consoleLogLevel === 'none', +const logger = createLogger({ + level: config.consoleLogLevel === 'none' ? Infinity : config.consoleLogLevel, }) checkEnvironment(logger) @@ -32,7 +31,8 @@ const witClient = new Wit({ accessToken: process.env['WIT_AI_TOKEN']!, }) -process.on('beforeExit', () => tesseractWorker.terminate()) +logger.fatal('test') +logger.error('test') // Server logic @@ -112,7 +112,7 @@ const server = fastify() // Start the server -logger.debug(`Starting with these configurations: ${inspectObject(config)}`, ) +logger.debug(`Starting with these configurations: ${inspectObject(config)}`) await server.listen({ host: config.address ?? '0.0.0.0', diff --git a/packages/shared/package.json b/packages/shared/package.json index 19746ba..c903ac0 100755 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -32,8 +32,9 @@ "dependencies": { "bson": "^6.2.0", "chalk": "^5.3.0", + "supports-color": "^9.4.0", + "tracer": "^1.3.0", "valibot": "^0.21.0", - "winston": "^3.11.0", "zod": "^3.22.4" } } diff --git a/packages/shared/src/utils/logger.ts b/packages/shared/src/utils/logger.ts index 085de1c..ad065a8 100644 --- a/packages/shared/src/utils/logger.ts +++ b/packages/shared/src/utils/logger.ts @@ -1,66 +1,43 @@ -import { createLogger as createWinstonLogger, LoggerOptions, transports, format } from 'winston' -import { Chalk, ChalkInstance } from 'chalk' +import { colorConsole, console as uncoloredConsole, Tracer } from 'tracer' +import { Chalk, supportsColor, supportsColorStderr } from 'chalk' const chalk = new Chalk() +const DefaultConfig = { + dateformat: 'DD/MM/YYYY HH:mm:ss.sss Z', + format: [ + '{{message}}', + { + error: `${chalk.bgRedBright.whiteBright(' ERROR ')} {{message}}\n${chalk.gray( + '{{stack}}', + )}`, + debug: chalk.gray('DEBUG: {{message}}\n{{stack}}'), + warn: `${chalk.bgYellowBright.whiteBright(' WARN ')} ${chalk.yellowBright('{{message}}')}\n${chalk.gray( + '{{stack}}', + )}`, + info: `${chalk.bgBlueBright.whiteBright(' INFO ')} ${chalk.cyanBright('{{message}}')}`, + fatal: `${chalk.bgRedBright.whiteBright(' FATAL ')} ${chalk.redBright('{{message}}')}\n${chalk.white( + '{{stack}}', + )}`, + log: '{{message}}', + trace: chalk.gray('[{{timestamp}}] TRACE: {{message}}\n{{stack}}'), + }, + ], + methods: ['debug', 'trace', 'log', 'info', 'warn', 'error', 'fatal'], + filters: [], +} satisfies Tracer.LoggerConfig -const LevelPrefixes = { - error: `${chalk.bgRed.whiteBright(' ERR! ')} `, - warn: `${chalk.bgYellow.black(' WARN ')} `, - info: `${chalk.bgBlue.whiteBright(' INFO ')} `, - log: chalk.reset(''), - debug: chalk.gray('DEBUG: '), - silly: chalk.gray('SILLY: '), -} as Record +export function createLogger(config: Omit) { + const combinedConfig = { ...DefaultConfig, ...config } -const LevelColorFunctions = { - error: chalk.redBright, - warn: chalk.yellowBright, - info: chalk.cyanBright, - log: chalk.reset, - debug: chalk.gray, - silly: chalk.gray, -} as Record - -export function createLogger( - serviceName: string, - config: SafeOmit< - LoggerOptions, - | 'defaultMeta' - | 'exceptionHandlers' - | 'exitOnError' - | 'handleExceptions' - | 'handleRejections' - | 'levels' - | 'rejectionHandlers' - >, -) { - const logger = createWinstonLogger({ - exitOnError: false, - defaultMeta: { serviceName }, - handleExceptions: true, - handleRejections: true, - transports: config.transports ?? [ - new transports.Console(), - new transports.File({ - dirname: 'logs', - filename: `${serviceName}-${Date.now()}.log`, - format: format.combine( - format.uncolorize(), - format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - format.printf( - ({ level, message, timestamp }) => `[${timestamp}] ${level.toUpperCase()}: ${message}`, - ), - ), - }), - ], - format: format.printf(({ level, message }) => LevelPrefixes[level] + LevelColorFunctions[level]!(message)), - ...config, - }) - - logger.silly(`Logger for ${serviceName} created at ${Date.now()}`) - - return logger + if ( + // biome-ignore lint/complexity/useOptionalChain: No Biome, this isn't a nullable check + supportsColor && + supportsColor.hasBasic && + supportsColorStderr && + supportsColorStderr.hasBasic + ) + return colorConsole(combinedConfig) + else return uncoloredConsole(combinedConfig) } -type SafeOmit = Omit export type Logger = ReturnType