import path from "node:path"; import fs from "node:fs"; import pino from "pino"; import { pinoHttp } from "pino-http"; import { readConfigFile } from "../config-file.js"; import { resolveDefaultLogsDir, resolveHomeAwarePath } from "../home-paths.js"; function resolveServerLogDir(): string { const envOverride = process.env.PAPERCLIP_LOG_DIR?.trim(); if (envOverride) return resolveHomeAwarePath(envOverride); const fileLogDir = readConfigFile()?.logging.logDir?.trim(); if (fileLogDir) return resolveHomeAwarePath(fileLogDir); return resolveDefaultLogsDir(); } const logDir = resolveServerLogDir(); fs.mkdirSync(logDir, { recursive: true }); const logFile = path.join(logDir, "server.log"); const sharedOpts = { translateTime: "HH:MM:ss", ignore: "pid,hostname", }; export const logger = pino({ level: "debug", }, pino.transport({ targets: [ { target: "pino-pretty", options: { ...sharedOpts, ignore: "pid,hostname,req,res,responseTime", colorize: true, destination: 1 }, level: "info", }, { target: "pino-pretty", options: { ...sharedOpts, colorize: false, destination: logFile, mkdir: true }, level: "debug", }, ], })); export const httpLogger = pinoHttp({ logger, customLogLevel(_req, res, err) { if (err || res.statusCode >= 500) return "error"; if (res.statusCode >= 400) return "warn"; return "info"; }, customSuccessMessage(req, res) { return `${req.method} ${req.url} ${res.statusCode}`; }, customErrorMessage(req, res) { return `${req.method} ${req.url} ${res.statusCode}`; }, customProps() { return {}; }, });