import pino, { Logger as PinoLogger } from "pino"; import type { LoggerService } from "./logger-service"; import { config } from "../../config"; export class PinoLoggerService implements LoggerService { private readonly logger: PinoLogger; constructor(name?: string, parent?: PinoLogger) { if (parent) { this.logger = parent.child({ name }); } else { // In Next.js, especially in the Edge runtime or during instrumentation, // pino transports (which use worker threads) can cause issues. // We disable transport in production and during instrumentation. const useTransport = config.isDevelopment && typeof window === "undefined"; this.logger = pino({ name: name || "app", level: config.logging.level, transport: useTransport ? { target: "pino-pretty", options: { colorize: true, }, } : undefined, }); } } trace(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).trace(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).trace(msg, ...args); } } debug(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).debug(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).debug(msg, ...args); } } info(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).info(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).info(msg, ...args); } } warn(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).warn(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).warn(msg, ...args); } } error(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).error(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).error(msg, ...args); } } fatal(msg: string, ...args: unknown[]) { if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).fatal(args[0] as object, msg, ...args.slice(1)); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.logger as any).fatal(msg, ...args); } } child(bindings: Record): LoggerService { const childPino = this.logger.child(bindings); const service = new PinoLoggerService(); // eslint-disable-next-line @typescript-eslint/no-explicit-any (service as any).logger = childPino; return service; } }