// server/utils/logging.ts - API 调试日志工具:为每次请求生成 requestId 并输出安全错误摘要。 import { randomUUID } from "node:crypto"; import { consola } from "consola"; type LogMeta = Record; /** 创建带 requestId、scope 和耗时统计的接口日志器 */ export const createApiLogger = (scope: string) => { const requestId = randomUUID(); const startedAt = Date.now(); const prefix = `[${scope}]`; const withBaseMeta = (meta?: LogMeta) => ({ requestId, ...(meta ?? {}) }); return { requestId, info(message: string, meta?: LogMeta) { consola.info(`${prefix} ${message}`, withBaseMeta(meta)); }, warn(message: string, meta?: LogMeta) { consola.warn(`${prefix} ${message}`, withBaseMeta(meta)); }, error(message: string, meta?: LogMeta) { consola.error(`${prefix} ${message}`, withBaseMeta(meta)); }, done(message: string = "完成", meta?: LogMeta) { consola.info( `${prefix} ${message}`, withBaseMeta({ ...(meta ?? {}), elapsedMs: Date.now() - startedAt }) ); } }; }; /** 将未知错误转换为可写入日志的安全摘要,避免把 cookie/key 等响应体细节打进日志 */ export const toSafeLogError = (error: unknown) => { const maybeError = error as { message?: string; name?: string; response?: { status?: number; }; stack?: string; status?: number; statusCode?: number; statusMessage?: string; }; return { name: maybeError.name, message: maybeError.message ?? maybeError.statusMessage, status: maybeError.status ?? maybeError.statusCode ?? maybeError.response?.status, stack: maybeError.stack }; };