File
Blob: src/worker/lib/ai/logging.ts
| 1 | import { AiErrorCode, type AiUsage } from "@/shared/ai"; |
| 2 | import type { EntitlementSurface, PageAccessLevel } from "@/shared/entitlements"; |
| 3 | import { createLogger, type Logger } from "@/worker/lib/logger"; |
| 4 | |
| 5 | export type AiAction = "rewrite" | "generate" | "summarize" | "ask"; |
| 6 | |
| 7 | export interface AiLogContext { |
| 8 | action: AiAction; |
| 9 | userId?: string; |
| 10 | workspaceId: string; |
| 11 | pageId: string; |
| 12 | surface: EntitlementSurface; |
| 13 | pageAccess: PageAccessLevel; |
| 14 | } |
| 15 | |
| 16 | export interface AiDenialContext { |
| 17 | action: AiAction; |
| 18 | userId?: string; |
| 19 | workspaceId: string; |
| 20 | pageId: string; |
| 21 | surface: EntitlementSurface; |
| 22 | pageAccess: PageAccessLevel; |
| 23 | } |
| 24 | |
| 25 | const log: Logger = createLogger("ai"); |
| 26 | |
| 27 | export function aiLogger(): Logger { |
| 28 | return log; |
| 29 | } |
| 30 | |
| 31 | export function logAiRequest(ctx: AiLogContext): void { |
| 32 | log.info("ai_request", { ...ctx }); |
| 33 | } |
| 34 | |
| 35 | export function logAiResponse( |
| 36 | ctx: AiLogContext, |
| 37 | startedAt: number, |
| 38 | outcome: "ok" | "error", |
| 39 | extra?: { usage?: AiUsage; errorCode?: AiErrorCode }, |
| 40 | ): void { |
| 41 | log.info("ai_response", { |
| 42 | ...ctx, |
| 43 | durationMs: Date.now() - startedAt, |
| 44 | outcome, |
| 45 | ...(extra?.usage ? { usage: extra.usage } : {}), |
| 46 | ...(extra?.errorCode ? { errorCode: extra.errorCode } : {}), |
| 47 | }); |
| 48 | } |
| 49 | |
| 50 | export function logAiDenied(ctx: AiDenialContext): void { |
| 51 | log.warn("ai_denied", { ...ctx }); |
| 52 | } |