Skip to content
Snippets Groups Projects
Commit 1c4d34f4 authored by Jérôme POIRIER's avatar Jérôme POIRIER
Browse files

feat: enhance winston logs exploitability

- One file by day rather by hour, up to 20mb
- Disable zippedArchive
- Display stack traces
- Add files prefix
parent a8580b5d
No related branches found
No related tags found
2 merge requests!2feat: enhance winston logs exploitability,!1Release
Pipeline #67096 passed
......@@ -12,6 +12,7 @@ RATE_LIMIT_MAX=5000
# *********************************************************************************************
APP_LOG_DIR=logs
APP_LOG_FILES_PREFIX=backend-files
# error < warn < log < debug < verbose
APP_LOG_MAX_LEVEL=debug
\ No newline at end of file
......@@ -24,6 +24,7 @@ export class ConfigService {
const envVarsSchema: Joi.ObjectSchema = Joi.object({
API_KEY: Joi.string().required(),
APP_LOG_DIR: Joi.string().required(),
APP_LOG_FILES_PREFIX: Joi.string().required(),
APP_LOG_MAX_LEVEL: Joi.string().required(),
BODY_PARSER_LIMIT: Joi.string().default('50mb'),
DOCUMENTS_DIR: Joi.string().required(),
......@@ -56,6 +57,10 @@ export class ConfigService {
return String(this.envConfig.APP_LOG_DIR);
}
public get appLogFilesPrefix(): string {
return String(this.envConfig.APP_LOG_FILES_PREFIX);
}
public get appLogMaxLevel(): string {
return String(this.envConfig.APP_LOG_MAX_LEVEL);
}
......
import { ConsoleLogger, Injectable, LogLevel, NotImplementedException, Scope } from '@nestjs/common';
import { ConsoleLogger, Injectable, LogLevel, Scope } from '@nestjs/common';
import * as winston from 'winston';
import * as DailyRotateFile from 'winston-daily-rotate-file';
......@@ -8,7 +8,7 @@ export class LoggerService extends ConsoleLogger {
appLogMaxLevelDefault: LogLevel = 'log';
levelsNotLoggedInConsole: LogLevel[]; // Don't want to display debug/verbose in console
constructor(context: string, appLogDir: string, appLogMaxLevel: LogLevel) {
constructor(context: string, appLogDir: string, appLogFilesPrefix: string, appLogMaxLevel: LogLevel) {
super(context);
if (this.nestLevels.indexOf(appLogMaxLevel) < 0) {
......@@ -22,7 +22,7 @@ export class LoggerService extends ConsoleLogger {
this.levelsNotLoggedInConsole = this.nestLevels.slice(this.nestLevels.indexOf(this.appLogMaxLevel) + 1);
this.createWinstonLoggers(appLogDir);
this.createWinstonLoggers(appLogDir, appLogFilesPrefix);
}
// *********************************************************************************************
......@@ -32,10 +32,9 @@ export class LoggerService extends ConsoleLogger {
winstonLoggers: winston.Logger[] = [];
private createWinstonLoggers(appLogDir: string): void {
const DailyOptions: any = {
datePattern: 'YYYY-MM-DD-HH',
zippedArchive: true,
private createWinstonLoggers(appLogDir: string, appLogFilesPrefix: string): void {
const dailyOptions: DailyRotateFile.DailyRotateFileTransportOptions = {
zippedArchive: false,
maxSize: '20m',
maxFiles: '14d',
};
......@@ -44,9 +43,11 @@ export class LoggerService extends ConsoleLogger {
// * Formatters
const readableFormat: winston.Logform.Format = winston.format.combine(
winston.format.errors({ stack: true }), // Cf. https://stackoverflow.com/a/58475687
winston.format.timestamp({ format: 'DD/MM/YYYY HH:mm:ss' }),
winston.format.printf(
({ level, message, timestamp, ...meta }) => `${timestamp} ${level.toUpperCase()} [${meta[Symbol.for('splat')]}] ${message}`,
({ level, message, timestamp, stack, ...meta }) =>
`${timestamp} ${level.toUpperCase()} [${meta[Symbol.for('splat')]}] ${level == 'error' ? stack : message}`,
),
);
......@@ -55,8 +56,8 @@ export class LoggerService extends ConsoleLogger {
(
[
{ level: 'error', filePrefix: 'error-readable-' },
{ level: this.appLogMaxLevel, filePrefix: 'all-readable-' },
{ level: 'error', filePrefix: appLogFilesPrefix + '-error-readable-' },
{ level: this.appLogMaxLevel, filePrefix: appLogFilesPrefix + '-all-readable-' },
] as { level: LogLevel; filePrefix: string }[]
).forEach((logger) => {
try {
......@@ -64,7 +65,12 @@ export class LoggerService extends ConsoleLogger {
winston.createLogger({
level: logger.level,
format: readableFormat,
transports: [new DailyRotateFile({ filename: appLogDir + `/${logger.filePrefix}%DATE%.log`, ...DailyOptions })],
transports: [
new DailyRotateFile({
filename: appLogDir + `/${logger.filePrefix}%DATE%.log`,
...dailyOptions,
} as DailyRotateFile.DailyRotateFileTransportOptions),
],
}),
);
} catch (error) {
......
......@@ -24,7 +24,7 @@ async function bootstrap() {
app.use(express.urlencoded({ limit: config.bodyParserLimit, extended: true }));
// Logger
app.useLogger(new LoggerService('AppModule', config.appLogDir, <LogLevel>config.appLogMaxLevel));
app.useLogger(new LoggerService('AppModule', config.appLogDir, config.appLogFilesPrefix, <LogLevel>config.appLogMaxLevel));
// Skip SSL certificate verification
https.globalAgent.options.rejectUnauthorized = false;
......
......@@ -5,6 +5,7 @@ metadata:
namespace: ns-spi-NAMESPACE_ENV-syn
data:
APP_LOG_DIR: "{{APP_LOG_DIR}}"
APP_LOG_FILES_PREFIX: "backend-files"
APP_LOG_MAX_LEVEL: "{{APP_LOG_MAX_LEVEL}}"
DOCUMENTS_DIR: "{{DOCUMENTS_DIR}}"
NODE_ENV: "{{NODE_ENV}}"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment