ai-chatbot/lib/observability/client-logger.ts

71 lines
1.7 KiB
TypeScript

import { redactLogArgs, redactValue } from "@/lib/observability/redaction";
function isClientLoggingEnabled() {
return (
process.env.NODE_ENV !== "production" ||
process.env.NEXT_PUBLIC_ENABLE_CLIENT_LOGS === "true"
);
}
function normalizeEvent(event: string) {
return event
.trim()
.replace(/^\[[^\]]+\]\s*/, "")
.replace(/[^a-zA-Z0-9]+/g, "_")
.replace(/^_+|_+$/g, "")
.toLowerCase()
.slice(0, 80) || "event";
}
const SENSITIVE_EVENT_PATTERN =
/(authorization|body|cookie|header|image url|messages received|password|prompt|request body|session|token)/i;
function writeClientLog(
level: "debug" | "info" | "warn" | "error",
scope: string,
event: string,
args: unknown[]
) {
if (!isClientLoggingEnabled()) return;
const payload = redactValue({
level,
scope,
event: normalizeEvent(event),
message: event,
...(args.length > 0
? {
meta: SENSITIVE_EVENT_PATTERN.test(event)
? { omitted: true, argCount: args.length }
: redactLogArgs(args),
}
: {}),
});
if (level === "error") {
console.error(payload);
return;
}
if (level === "warn") {
console.warn(payload);
return;
}
console.log(payload);
}
export function createClientLogger(scope: string) {
return {
debug(event: string, ...args: unknown[]) {
writeClientLog("debug", scope, event, args);
},
info(event: string, ...args: unknown[]) {
writeClientLog("info", scope, event, args);
},
warn(event: string, ...args: unknown[]) {
writeClientLog("warn", scope, event, args);
},
error(event: string, ...args: unknown[]) {
writeClientLog("error", scope, event, args);
},
};
}