| // apps/api/src/log.ts | |
| // Structured logger with API-key redaction. Per-request child loggers | |
| // carry req_id; per-job/item children attach job_id / item_id. | |
| import pino from "pino"; | |
| export interface LogContext { | |
| reqId?: string; | |
| jobId?: string; | |
| itemId?: string; | |
| } | |
| const REDACT_PATHS = [ | |
| // outgoing fetch headers | |
| '*.headers.authorization', | |
| '*.headers.Authorization', | |
| '*.headers["api-key"]', | |
| // settings or options snapshot fields | |
| "*.apiKey", | |
| "*.api_key", | |
| "*.judge.apiKey", | |
| "*.rubricGeneration.apiKey", | |
| // any nested options snapshot column | |
| "options_snapshot.apiKey", | |
| "options_snapshot.judge.apiKey", | |
| "options_snapshot.rubricGeneration.apiKey", | |
| ]; | |
| export function createLogger(level: string) { | |
| return pino({ | |
| level, | |
| redact: { | |
| paths: REDACT_PATHS, | |
| censor: "[REDACTED]", | |
| }, | |
| // pino-pretty in dev only; runtime uses JSON | |
| transport: | |
| process.env.NODE_ENV === "production" | |
| ? undefined | |
| : { | |
| target: "pino-pretty", | |
| options: { colorize: true, translateTime: "HH:MM:ss.l" }, | |
| }, | |
| }); | |
| } | |
| export type Logger = ReturnType<typeof createLogger>; | |