server/utils/loggers.ts

145 lines
4.2 KiB
TypeScript
Raw Normal View History

import { mkdir } from "node:fs/promises";
import { dirname } from "node:path";
import { getRotatingFileSink } from "@logtape/file";
import {
configure,
getConsoleSink,
getLevelFilter,
2025-04-10 19:15:31 +02:00
type LogLevel,
type LogRecord,
} from "@logtape/logtape";
import chalk from "chalk";
import { config } from "~/config.ts";
2024-04-14 13:20:55 +02:00
// config.logging.log_file_path is a path to a file, create the directory if it doesn't exist
await mkdir(dirname(config.logging.log_file_path), { recursive: true });
const levelAbbreviations: Record<LogLevel, string> = {
debug: "DBG",
info: "INF",
warning: "WRN",
error: "ERR",
fatal: "FTL",
2025-06-15 02:24:56 +02:00
trace: "TRC",
};
2024-04-14 13:20:55 +02:00
/**
* The styles for the log level in the console.
*/
const logLevelStyles: Record<LogLevel, (text: string) => string> = {
debug: chalk.white.bgGray,
info: chalk.black.bgWhite,
warning: chalk.black.bgYellow,
error: chalk.white.bgRed,
fatal: chalk.white.bgRedBright,
2025-06-15 02:24:56 +02:00
trace: chalk.white.bgBlue,
};
/**
* The default console formatter.
*
* @param record The log record to format.
* @returns The formatted log record, as an array of arguments for
2025-02-25 23:32:05 +01:00
* {@link console.log}.
*/
export function defaultConsoleFormatter(record: LogRecord): string[] {
const msg = record.message.join("");
const date = new Date(record.timestamp);
const time = `${date.getUTCHours().toString().padStart(2, "0")}:${date
.getUTCMinutes()
.toString()
.padStart(
2,
"0",
)}:${date.getUTCSeconds().toString().padStart(2, "0")}.${date
.getUTCMilliseconds()
.toString()
.padStart(3, "0")}`;
const formattedTime = chalk.gray(time);
const formattedLevel = logLevelStyles[record.level](
levelAbbreviations[record.level],
);
const formattedCategory = chalk.gray(record.category.join("\xb7"));
const formattedMsg = chalk.reset(msg);
return [
`${formattedTime} ${formattedLevel} ${formattedCategory} ${formattedMsg}`,
];
}
export const configureLoggers = (silent = false): Promise<void> =>
configure({
reset: true,
sinks: {
console: getConsoleSink({
formatter: defaultConsoleFormatter,
}),
2025-02-25 23:32:05 +01:00
file: getRotatingFileSink(config.logging.log_file_path, {
maxFiles: 10,
maxSize: 10 * 1024 * 1024,
}),
},
filters: {
configFilter: silent
? getLevelFilter(null)
: getLevelFilter(config.logging.log_level),
},
loggers: [
{
category: "server",
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["federation", "inbox"],
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["federation", "delivery"],
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["federation", "bridge"],
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["federation", "resolvers"],
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["federation", "messaging"],
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: "database",
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: "webfinger",
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: "sonic",
sinks: ["console", "file"],
filters: ["configFilter"],
},
{
category: ["logtape", "meta"],
2024-11-28 10:26:28 +01:00
lowestLevel: "error",
},
{
category: "plugin",
sinks: ["console", "file"],
filters: ["configFilter"],
},
],
});