81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { redactLogArgs, redactValue } from "@/lib/observability/redaction";
|
|
|
|
type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
|
|
const LEVEL_ORDER: Record<LogLevel, number> = {
|
|
debug: 10,
|
|
info: 20,
|
|
warn: 30,
|
|
error: 40,
|
|
silent: 50,
|
|
};
|
|
const SENSITIVE_EVENT_PATTERN =
|
|
/(authorization|body|cookie|header|image url|messages received|password|prompt|request body|session|token)/i;
|
|
|
|
function resolveLogLevel(): LogLevel {
|
|
const configured = String(process.env.LOG_LEVEL || "").toLowerCase();
|
|
if (configured in LEVEL_ORDER) return configured as LogLevel;
|
|
return process.env.NODE_ENV === "production" ? "info" : "debug";
|
|
}
|
|
|
|
function shouldLog(level: Exclude<LogLevel, "silent">) {
|
|
return LEVEL_ORDER[level] >= LEVEL_ORDER[resolveLogLevel()];
|
|
}
|
|
|
|
function normalizeEvent(event: string) {
|
|
return event
|
|
.trim()
|
|
.replace(/^\[[^\]]+\]\s*/, "")
|
|
.replace(/[^a-zA-Z0-9]+/g, "_")
|
|
.replace(/^_+|_+$/g, "")
|
|
.toLowerCase()
|
|
.slice(0, 80) || "event";
|
|
}
|
|
|
|
function writeLog(level: Exclude<LogLevel, "silent">, scope: string, event: string, args: unknown[]) {
|
|
if (!shouldLog(level)) return;
|
|
|
|
const payload = {
|
|
level,
|
|
scope,
|
|
event: normalizeEvent(event),
|
|
message: event,
|
|
timestamp: new Date().toISOString(),
|
|
...(args.length > 0
|
|
? {
|
|
meta: SENSITIVE_EVENT_PATTERN.test(event)
|
|
? { omitted: true, argCount: args.length }
|
|
: redactLogArgs(args),
|
|
}
|
|
: {}),
|
|
};
|
|
|
|
const serialized = JSON.stringify(redactValue(payload));
|
|
if (level === "error") {
|
|
console.error(serialized);
|
|
return;
|
|
}
|
|
if (level === "warn") {
|
|
console.warn(serialized);
|
|
return;
|
|
}
|
|
console.log(serialized);
|
|
}
|
|
|
|
export function createLogger(scope: string) {
|
|
return {
|
|
debug(event: string, ...args: unknown[]) {
|
|
writeLog("debug", scope, event, args);
|
|
},
|
|
info(event: string, ...args: unknown[]) {
|
|
writeLog("info", scope, event, args);
|
|
},
|
|
warn(event: string, ...args: unknown[]) {
|
|
writeLog("warn", scope, event, args);
|
|
},
|
|
error(event: string, ...args: unknown[]) {
|
|
writeLog("error", scope, event, args);
|
|
},
|
|
};
|
|
}
|