Files
zkldi_Tachi/server/src/lib/logger/logger.ts
T
2021-06-26 01:36:39 +01:00

161 lines
3.9 KiB
TypeScript

import winston, { format, transports, Logger, LeveledLogMethod } from "winston";
import { EscapeStringRegexp } from "../../utils/misc";
import { LOG_LEVEL } from "../setup/config";
export type KtLogger = Logger & { severe: LeveledLogMethod };
const level = LOG_LEVEL ?? "info";
const IN_TESTING = process.env.NODE_ENV === "test";
const formatExcessProperties = (meta: Record<string, unknown>) => {
let i = 0;
for (const key in meta) {
const val = meta[key];
if (val instanceof Error) {
meta[key] = { message: val.message, stack: val.stack };
}
i++;
}
if (!i) {
return "";
}
return ` ${JSON.stringify(meta)}`;
};
const formatExcessPropertiesNoStack = (meta: Record<string, unknown>, omitKeys: string[] = []) => {
let i = 0;
const realMeta: Record<string, unknown> = {};
for (const key in meta) {
if (omitKeys.includes(key)) {
continue;
}
const val = meta[key];
if (val instanceof Error) {
realMeta[key] = { message: val.message };
} else {
realMeta[key] = val;
}
i++;
}
if (!i) {
return "";
}
return ` ${JSON.stringify(realMeta)}`;
};
const ktblackPrintf = format.printf(
({ level, message, context = "ktblack-root", timestamp, ...meta }) =>
`${timestamp} [${
Array.isArray(context) ? context.join(" | ") : context
}] ${level}: ${message}${formatExcessProperties(meta)}`
);
const ktblackConsolePrintf = format.printf(
({ level, message, context = "ktblack-root", timestamp, hideFromConsole, ...meta }) =>
`${timestamp} [${
Array.isArray(context) ? context.join(" | ") : context
}] ${level}: ${message}${formatExcessPropertiesNoStack(meta, hideFromConsole)}`
);
winston.addColors({
crit: ["bgRed", "black"],
severe: ["bgBrightRed", "black"],
error: ["red"],
warn: ["yellow"],
info: ["blue"],
verbose: ["cyan"],
debug: ["white"],
});
const baseFormatRoute = format.combine(
format.timestamp({
format: "YYYY-MM-DD HH:mm:ss",
})
);
const defaultFormatRoute = format.combine(
baseFormatRoute,
format.errors({ stack: false }),
ktblackPrintf
);
const consoleFormatRoute = format.combine(
baseFormatRoute,
format.errors({ stack: false }),
ktblackConsolePrintf,
format.colorize({
all: true,
})
);
let tports = [];
/* istanbul ignore next */
if (IN_TESTING) {
tports = [
new transports.Console({
format: consoleFormatRoute,
}),
];
} else {
tports = [
new transports.File({
filename: "logs/ktblack-error.log",
level: "error",
format: defaultFormatRoute,
}),
new transports.File({ filename: "logs/ktblack.log", format: defaultFormatRoute }),
new transports.Console({
format: consoleFormatRoute,
}),
];
}
export const rootLogger = winston.createLogger({
levels: {
crit: 0, // entire process termination is necessary
severe: 1, // something is wrong, and more than one function is affected (such as a failed assertion that is definitely expected to be true).
error: 2, // function call (or related process) has failed unexpectedly
warn: 3, // function call has hit something it didn't want, but can recover
info: 4, // something has happened that is expected, but worth logging
verbose: 5, // something has happened
debug: 6, // glorified console.log debugging
},
level,
format: defaultFormatRoute,
transports: tports,
});
function CreateLogCtx(filename: string, lg = rootLogger): KtLogger {
const replacedFilename = filename.replace(
new RegExp(`^${EscapeStringRegexp(process.cwd())}/((js|src)/)?`, "u"),
""
);
const logger = lg.child({
context: [replacedFilename],
}) as KtLogger;
logger.defaultMeta = { context: [replacedFilename] };
return logger;
}
export function AppendLogCtx(context: string, lg: KtLogger): KtLogger {
const newContext = [...lg.defaultMeta.context, context];
return lg.child({ context: newContext }) as KtLogger;
}
export const Transports = tports;
export default CreateLogCtx;