paperclip/server/src/middleware/logger.ts
Dotta 690149d555 Fix 500 error logging to show actual error instead of generic message
pino-http checks res.err before falling back to its generic
"failed with status code 500" error. Set res.err to the real error
in the error handler so logs include the actual message and stack trace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:28:26 -06:00

61 lines
1.6 KiB
TypeScript

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 {};
},
});