Files
cfw-autumn/packages/logging/src/streams/prettyLogStream.ts
2026-06-05 18:52:26 +01:00

118 lines
2.4 KiB
TypeScript

import { Writable } from "node:stream";
const FORMATTED_LOG_EXCLUDE_FIELDS = new Set([
"time",
"level",
"msg",
"pid",
"hostname",
"req",
"res",
"statusCode",
"body",
"query",
"durationMs",
"duration_ms",
"event",
"context",
"workflow",
"trigger",
"stripe_event",
"vercel_event",
"worker",
"extras",
"type",
"data",
"aws",
"service",
]);
const colors = {
reset: "\x1b[0m",
bright: "\x1b[1m",
red: "\x1b[31m",
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
white: "\x1b[37m",
gray: "\x1b[90m",
bgRed: "\x1b[41m",
};
const levelColors: Record<number | string, string> = {
10: colors.gray,
20: colors.blue,
30: colors.green,
40: colors.yellow,
50: colors.red,
60: colors.bgRed,
TRACE: colors.gray,
DEBUG: colors.blue,
INFO: colors.green,
WARN: colors.yellow,
ERROR: colors.red,
FATAL: colors.bgRed,
};
const levelNames: Record<number | string, string> = {
10: "TRACE",
20: "DEBUG",
30: "INFO",
40: "WARN",
50: "ERROR",
60: "FATAL",
TRACE: "TRACE",
DEBUG: "DEBUG",
INFO: "INFO",
WARN: "WARN",
ERROR: "ERROR",
FATAL: "FATAL",
};
export const createPrettyLogStream = ({
trailingNewline = true,
useConsoleLog = false,
}: {
trailingNewline?: boolean;
useConsoleLog?: boolean;
} = {}) =>
new Writable({
write(chunk, _encoding, callback) {
try {
const log = JSON.parse(chunk.toString());
const timestamp = new Date(log.time)
.toISOString()
.replace("T", " ")
.replace("Z", "");
const level = log.level;
const levelColor = levelColors[level] || colors.white;
const levelName =
levelNames[level] || (typeof level === "string" ? level : "UNKNOWN");
let message = log.msg || "";
const additionalFields = Object.keys(log)
.filter((key) => !FORMATTED_LOG_EXCLUDE_FIELDS.has(key))
.reduce(
(acc, key) => {
acc[key] = log[key];
return acc;
},
{} as Record<string, unknown>,
);
if (Object.keys(additionalFields).length > 0) {
message += ` ${JSON.stringify(additionalFields, null, 2)}`;
}
const formattedLog = `${colors.gray}${timestamp}${colors.reset} ${levelColor}${colors.bright}${levelName}${colors.reset} ${message}${trailingNewline ? "\n" : ""}`;
if (useConsoleLog) console.log(formattedLog);
else process.stdout.write(formattedLog);
callback();
} catch {
if (useConsoleLog) console.log(chunk.toString());
else process.stdout.write(chunk);
callback();
}
},
});