hedgedoc/backend/src/logger/console-logger.service.ts
Tilman Vatteroth bf30cbcf48 fix(repository): Move backend code into subdirectory
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
2022-10-30 22:46:42 +01:00

181 lines
4.6 KiB
TypeScript

/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
Inject,
Injectable,
LoggerService,
Optional,
Scope,
} from '@nestjs/common';
import { isObject } from '@nestjs/common/utils/shared.utils';
import appConfiguration, { AppConfig } from '../config/app.config';
import { Loglevel } from '../config/loglevel.enum';
import { needToLog } from '../config/utils';
import clc = require('cli-color');
import DateTimeFormatOptions = Intl.DateTimeFormatOptions;
@Injectable({ scope: Scope.TRANSIENT })
export class ConsoleLoggerService implements LoggerService {
private classContext: string | undefined;
private lastTimestamp: number;
private skipColor = false;
constructor(
@Inject(appConfiguration.KEY)
private appConfig: AppConfig,
@Optional() context?: string,
) {
this.classContext = context;
}
setContext(context: string): void {
this.classContext = context;
}
setSkipColor(skipColor: boolean): void {
this.skipColor = skipColor;
}
error(message: unknown, trace = '', functionContext?: string): void {
this.printMessage(
message,
clc.red,
this.makeContextString(functionContext),
false,
);
ConsoleLoggerService.printStackTrace(trace);
}
log(message: unknown, functionContext?: string): void {
if (needToLog(this.appConfig.loglevel, Loglevel.INFO)) {
this.printMessage(
message,
clc.green,
this.makeContextString(functionContext),
false,
);
}
}
warn(message: unknown, functionContext?: string): void {
if (needToLog(this.appConfig.loglevel, Loglevel.WARN)) {
this.printMessage(
message,
clc.yellow,
this.makeContextString(functionContext),
false,
);
}
}
debug(message: unknown, functionContext?: string): void {
if (needToLog(this.appConfig.loglevel, Loglevel.DEBUG)) {
this.printMessage(
message,
clc.magentaBright,
this.makeContextString(functionContext),
false,
);
}
}
verbose(message: unknown, functionContext?: string): void {
if (needToLog(this.appConfig.loglevel, Loglevel.TRACE)) {
this.printMessage(
message,
clc.cyanBright,
this.makeContextString(functionContext),
false,
);
}
}
private makeContextString(functionContext?: string): string {
let context = this.classContext;
if (!context) {
context = 'HedgeDoc';
}
if (functionContext) {
context += '.' + functionContext + '()';
}
return context;
}
static sanitize(input: string): string {
return (
input
// remove ASCII control characters
.replace(/\p{C}/gu, '')
// replace all non-zeros width spaces with one space
.replace(/\p{Zs}/gu, ' ')
);
}
private printMessage(
message: unknown,
color: (message: string) => string,
context = '',
isTimeDiffEnabled?: boolean,
): void {
let output;
// if skipColor is set, we do not use colors and skip sanitizing
if (this.skipColor) {
if (isObject(message)) {
output = `${color('Object:')}\n${JSON.stringify(message, null, 2)}\n`;
} else {
output = message as string;
}
} else {
if (isObject(message)) {
output = `${color('Object:')}\n${ConsoleLoggerService.sanitize(
JSON.stringify(message, null, 2),
)}\n`;
} else {
output = color(ConsoleLoggerService.sanitize(message as string));
}
}
const localeStringOptions: DateTimeFormatOptions = {
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
day: '2-digit',
month: '2-digit',
};
//TODO make timestamp optional
const timestamp = new Date(Date.now()).toLocaleString(
undefined,
localeStringOptions,
);
const contextMessage = context ? clc.blue(`[${context}] `) : '';
const timestampDiff = this.updateAndGetTimestampDiff(isTimeDiffEnabled);
process.stdout.write(
`${timestamp} ${contextMessage}${output}${timestampDiff}\n`,
);
}
private updateAndGetTimestampDiff(isTimeDiffEnabled?: boolean): string {
const includeTimestamp = this.lastTimestamp && isTimeDiffEnabled;
const result = includeTimestamp
? clc.yellow(` +${Date.now() - this.lastTimestamp}ms`)
: '';
this.lastTimestamp = Date.now();
return result;
}
private static printStackTrace(trace: string): void {
if (!trace) {
return;
}
process.stdout.write(`${trace}\n`);
}
}