71 lines
1.7 KiB
TypeScript
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);
|
|
},
|
|
};
|
|
}
|