src/logger.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
import { type ILogger, LogLevel } from "@sapphire/framework";
import pino, { type Logger as PinoInstance } from "pino";
import config from "@/config";
export class PinoSapphireLogger implements ILogger {
private pino: PinoInstance;
private minLevel: LogLevel;
constructor(options?: pino.LoggerOptions, minLevel: LogLevel = LogLevel.Info) {
this.minLevel = minLevel;
this.pino = pino({
transport: config.isProduction
? undefined
: { target: "pino-pretty", options: { colorize: true } },
base: {
pid: false,
},
level: "trace",
...options,
});
}
public has(level: LogLevel): boolean {
return level >= this.minLevel && level !== LogLevel.None;
}
public write(level: LogLevel, ...values: readonly unknown[]): void {
if (!this.has(level)) return;
const { name, msg, obj } = this.extractModuleAndPayload(values);
const payload = { name, ...obj };
switch (level) {
case LogLevel.Trace:
this.pino.trace(payload, msg);
break;
case LogLevel.Debug:
this.pino.debug(payload, msg);
break;
case LogLevel.Info:
this.pino.info(payload, msg);
break;
case LogLevel.Warn:
this.pino.warn(payload, msg);
break;
case LogLevel.Error:
this.pino.error(payload, msg);
break;
case LogLevel.Fatal:
this.pino.fatal(payload, msg);
break;
default:
break;
}
}
public trace(...values: readonly unknown[]): void {
this.write(LogLevel.Trace, ...values);
}
public debug(...values: readonly unknown[]): void {
this.write(LogLevel.Debug, ...values);
}
public info(...values: readonly unknown[]): void {
this.write(LogLevel.Info, ...values);
}
public warn(...values: readonly unknown[]): void {
this.write(LogLevel.Warn, ...values);
}
public error(...values: readonly unknown[]): void {
this.write(LogLevel.Error, ...values);
}
public fatal(...values: readonly unknown[]): void {
this.write(LogLevel.Fatal, ...values);
}
private extractModuleAndPayload(values: readonly unknown[]): {
name: string;
msg: string;
obj?: Record<string, unknown>;
} {
let name = "sapphire";
let msg = "";
let err: Error | undefined = undefined;
const extra: unknown[] = [];
const args = [...values];
if (args.length > 0 && typeof args[0] === "string") {
const firstArg = args[0];
const colonIndex = firstArg.indexOf(":");
if (colonIndex !== -1) {
name = firstArg.substring(0, colonIndex).trim();
const remainingMessage = firstArg.substring(colonIndex + 1).trim();
if (remainingMessage) args[0] = remainingMessage;
else args.shift();
}
}
for (const val of args) {
if (val instanceof Error) err = val;
else if (typeof val === "object" && val !== null) extra.push(val);
else msg += (msg ? " " : "") + String(val);
}
const obj: Record<string, any> = {};
if (err) obj.err = err;
if (extra.length > 0) obj.extra = extra;
return { name, msg, obj };
}
}
|