ffffng/server/logger.ts

100 lines
3.8 KiB
TypeScript

import {
isString,
Logger,
LoggingConfig,
LogLevel,
TaggedLogger,
} from "./types";
import moment from "moment";
export type LoggingFunction = (...args: unknown[]) => void;
// noinspection JSUnusedLocalSymbols
const noopTaggedLogger: TaggedLogger = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
log(level: LogLevel, ...args: unknown[]): void {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
debug(...args: unknown[]): void {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
info(...args: unknown[]): void {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
warn(...args: unknown[]): void {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
error(...args: unknown[]): void {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
profile(...args: unknown[]): void {},
};
export interface ActivatableLogger extends Logger {
init(config: LoggingConfig, loggingFunction?: LoggingFunction): void;
}
/**
* TODO: Check if LoggingConfig.debug and LoggingConfig.profile are handled.
*/
export class ActivatableLoggerImpl implements ActivatableLogger {
private config: LoggingConfig = new LoggingConfig(false, false, false);
private loggingFunction: LoggingFunction = console.info;
init(config: LoggingConfig, loggingFunction?: LoggingFunction): void {
this.config = config;
this.loggingFunction = loggingFunction || console.info;
}
tag(...tags: string[]): TaggedLogger {
if (this.config.enabled) {
const debug = this.config.debug;
const profile = this.config.profile;
const loggingFunction = this.loggingFunction;
return {
log(level: LogLevel, ...args: unknown[]): void {
const timeStr = moment().format("YYYY-MM-DD HH:mm:ss");
const levelStr = level.toUpperCase();
const tagsStr = tags ? "[" + tags.join(", ") + "]" : "";
const messagePrefix = `${timeStr} ${levelStr} - ${tagsStr}`;
// Make sure to only replace %s, etc. in real log message
// but not in tags.
const escapedMessagePrefix = messagePrefix.replace(
/%/g,
"%%"
);
let message = "";
if (args && isString(args[0])) {
message = args[0];
args.shift();
}
const logStr = message
? `${escapedMessagePrefix} ${message}`
: escapedMessagePrefix;
loggingFunction(logStr, ...args);
},
debug(...args: unknown[]): void {
if (debug) {
this.log("debug", ...args);
}
},
info(...args: unknown[]): void {
this.log("info", ...args);
},
warn(...args: unknown[]): void {
this.log("warn", ...args);
},
error(...args: unknown[]): void {
this.log("error", ...args);
},
profile(...args: unknown[]): void {
if (profile) {
this.log("profile", ...args);
}
},
};
} else {
return noopTaggedLogger;
}
}
}
export default new ActivatableLoggerImpl() as ActivatableLogger;