SPB Git

spb/autoscholar

Public
1.7 KB · 53 lines typescript
1import { randomUUID } from "node:crypto";2import pino, { type Logger } from "pino";34const SECRET_KEYS = /(password|secret|token|api[-_]?key|authorization|cookie|credential|private[-_]?key)/i;5const SECRET_VALUES = [6  /sk-ant-[A-Za-z0-9_-]{10,}/g,7  /Bearer\s+[A-Za-z0-9._-]{10,}/g,8  /asw_[A-Za-z0-9_-]{10,}/g,9];1011/** Redacts secret-looking keys/values from any JSON-serialisable value (used for logs, events and public provenance). */12export function redact<T>(value: T): T {13  if (typeof value === "string") {14    let out: string = value;15    for (const re of SECRET_VALUES) out = out.replace(re, "[REDACTED]");16    return out as unknown as T;17  }18  if (value instanceof Date) return value;19  if (Buffer.isBuffer(value)) return value;20  if (Array.isArray(value)) return value.map((v) => redact(v)) as T;21  if (value && typeof value === "object") {22    const out: Record<string, unknown> = {};23    for (const [k, v] of Object.entries(value as Record<string, unknown>)) {24      out[k] = SECRET_KEYS.test(k) ? "[REDACTED]" : redact(v);25    }26    return out as T;27  }28  return value;29}3031export function createLogger(service: string, level = process.env.LOG_LEVEL ?? "info"): Logger {32  return pino({33    level,34    base: { service, pid: process.pid },35    timestamp: pino.stdTimeFunctions.isoTime,36    formatters: { level: (label) => ({ level: label }) },37    hooks: {38      logMethod(args, method) {39        const safe = args.map((a) =>40          typeof a === "object" && a !== null ? redact(a) : typeof a === "string" ? redact(a) : a,41        );42        return method.apply(this, safe as Parameters<typeof method>);43      },44    },45  });46}4748export function correlationId(): string {49  return randomUUID();50}5152export type { Logger };53
Files · 883c053b0551cd621fd5686bc6281da55732b9a4
Menu

Theme