【免费下载链接】waoowaoo首家工业级全流程 AI 影视生产平台。Industry-first professional AI Agent platform for controllable film video production. From shorts to live-action with Hollywood-standard workflows.项目地址https://gitcode.com/gh_mirrors/wa/waoowaoo点击查看免费下载本文以 waoowaoo工业级全流程 AI 影视生产平台的日志与可观测性架构契约为主线系统讲解其日志即唯一结构化事件流、业务原文只存数据库的设计哲学以及 LG-01~LG-08 八条不变量在源码中的落地方式。读完你将掌握如何用单一出口产出单行 JSON 日志并统一脱敏、如何通过 AsyncLocalStorage 传播 requestId/taskId 等关联维度、如何设计绕过级别过滤的 audit 审计通道与alert.*告警命名空间以及如何用 ESLint 而非自研脚本守住no-console边界。为什么是这样日志不是第二份业务数据库waoowaoo 的日志架构决策以一句否定式命题为核心日志是运行观测事实的单一结构化流不是第二份业务数据库。所有服务端进程把 JSON 事件写到 stdout这是唯一权威输出流采集、检索和告警都以它为准。落盘文件logs/app.log只是自托管管理员下载用的便利副本不承担正确性。由此导出一条硬性约束日志只记 identity、摘要与耗时。业务原文的唯一权威在数据库——从日志内容反推业务状态属于架构违规。例如 LLM 调用的 Prompt 全文、模型 raw output、创作内容、用户上传内容均不得进入日志敏感键在唯一出口统一脱敏LG-03。该契约在架构契约目录中被归类为结构化日志、审计通道与告警命名空间模块遵循其四节固定结构为什么是这样 / 不变量 / 权威入口 / 踩过的坑并严格执行违反后果是钱、数据或越权的准入三问——凡是能被 check 脚本强制的、会随实现细节变化的、仅属代码风格的内容都不进入模块文档。八条不变量日志系统的稳定契约LG-01 — stdout JSON 是权威日志流所有服务端日志经唯一 write 出口序列化为单行 JSON。落盘副本全局单文件、超阈值原子 rename 轮转、fire-and-forget、失败不影响应用禁止恢复 per-project 或 per-task 分文件写入。在core.ts中唯一写出点write()完成等级过滤、audit 旁路、上下文合并、脱敏、抑制判定后调用JSON.stringify序列化为单行ERROR 走console.error、其余走console.log随后 fire-and-forget 调用文件写入function write(level: LogLevel, event: OmitLogEvent, ts | level | service): void { const shouldEmitByLevel shouldLogLevel(level) const shouldEmitAudit Boolean(event.audit) LOG_CONFIG.auditEnabled if (!shouldEmitByLevel !shouldEmitAudit) return // ... 合并上下文、脱敏、抑制判定 const line JSON.stringify(safeEvent) if (level ERROR) console.error(line) else console.log(line) writeLogLineToFile(line) }LG-02 — 事件字段契约唯一结构由共享LogEvent类型定义时间、级别、service、audit、module、action、message、关联 identity、失败语义、耗时、details、error。新增关联维度必须扩展该契约禁止把 identity 埋进 details 或 message 字符串。types.ts 定义了完整的字段契约export interface LogEvent { ts: string level: LogLevel service: string audit?: boolean module?: string action?: string message: string requestId?: string providerRequestId?: string taskId?: string taskAttempt?: number threadId?: string turnId?: string operationId?: string projectId?: string userId?: string errorCode?: string retryable?: boolean durationMs?: number provider?: string details?: Recordstring, unknown | unknown[] | null error?: ErrorFields }从源码结构可以看出关联 identity 覆盖了 requestId、providerRequestId、taskId/taskAttempt、threadId/turnId、operationId、projectId、userId 七个维度——它们是顶层字段绝不内嵌到 details 或 message。LG-03 — 只记 ID、摘要与耗时不得记录业务原文。敏感键在唯一出口统一脱敏。脱敏实现在redact.ts递归深度上限MAX_DEPTH 6超限返回[MaxDepth]键名经归一化去掉所有非字母数字字符后做子串匹配使api_key/x-api-key/apiKey/Access-Key等变体命中同一个 needlefunction normalizeKey(key: string): string { return key.toLowerCase().replace(/[^a-z0-9]/g, ) }类实例如 Headers、请求配置对象也按可枚举自有属性递归脱敏防止JSON.stringify把未脱敏的内部字段原样序列化脱敏值统一替换为[REDACTED]。LG-04 — audit 通道语义审计事件绕过级别过滤保留给必须可追溯的用户操作、账本与认证审计且必须携带顶层 userId可得时。在write()中审计旁路的判定是shouldEmitAudit Boolean(event.audit) LOG_CONFIG.auditEnabled——即使事件等级低于当前阈值只要带 audit 标记仍会输出与级别过滤正交。semantic.ts 提供了两个高层封装logProjectAction与logAuthAction均以audit: true事件落库并显式传递 userIdexport function logAuthAction(action, message, details?, userId?, username?): void { createScopedLogger({ module: auth }).event({ level: INFO, audit: true, action, message: typeof message string ? message : action, userId, details: { ..., username }, }) }真实调用面覆盖登录限流route.ts、密码认证各分支password-auth.ts以及项目级操作config-ops.ts。LG-05 —alert.*action 命名空间保留需要外部告警路由的事件使用该前缀告警筛选只按 action 命名空间不按 message 文本匹配。仓库中真实存在多例例如计费服务的alert.billing.rollback_failed以及实时计费网关中的alert.billing.llm_realtime_uncovered、alert.billing.llm_stream_usage_too_large等一整套以alert.billing.*命名的告警事件。把是否告警编码进 action 前缀而非 message 文本保证告警路由可被机器稳定解析。LG-06 — no-console 由 ESLint 唯一裁决豁免仅限权威流的最终写出点与 logger 就绪前的独立 bootstrap 进程。禁止另建自研 console 扫描脚本。eslint.config.mjs 中对src/**/*.{ts,tsx}开启no-console: error豁免名单精确到文件src/lib/logging/core.ts、src/lib/logging/file-writer.tsstdout 权威日志流的最终写出点src/lib/storage/init.ts独立 bootstrap 进程logger 就绪前运行scripts/**运维/治理脚本整体豁免。任何在业务代码中新增的console.log都会直接触发 ESLint 错误。LG-07 — 语义 action 由所属生命周期契约拥有关键 action 必须与其唯一生命周期 owner 同步演进禁止用源码字符串或文件存在性脚本冒充运行协议 oracle。这条不变量解释了仓库中自研 console 扫描脚本与源码字符串存在性脚本被先后删除的治理背景协议的可信来源只能是类型、registry、policy 等机器可执行定义而不是对字符串的静态扫描。LG-08 — 用户、Assistant 与内部投影分离公开 UI 只携带可公开的 request/task/turn identity 与本地化字段原始 cause、Provider detail 与 stack 只进服务端日志或持久失败事实。Assistant 可获得的同一 FailureRecord 脱敏信息限于 name/message/code/status/request id 与阶段不得获得 secret、stack、业务原文或未脱敏 metadata。权威入口与调用链事件构造与唯一写出、上下文传播、语义封装、配置与脱敏src/lib/logging/**浏览器未知异常上报client-reporter.ts 与 /api/client-log只承担诊断守卫eslint.config.mjs 的 no-console。核心调用面从 API 请求到日志事件一个典型调用链是路由处理器用withLogContext({ requestId, userId, projectId })包裹业务执行业务层通过createScopedLogger({ module, action })拿到带语义上下文的 logger最终在write()统一合并LOG_CONFIGservice、级别、脱敏键与当前上下文后单行 JSON 输出。其中context.ts的上下文存储基于node:async_hooks.AsyncLocalStorage实现使异步链路含 Provider 轮询、Task 重试中的日志事件自动继承发起时的 requestId/taskId浏览器端则返回null并回退到模块级 fallbackContext。语义化日志的两种姿势顶层函数logDebug/logInfo/logWarn/logError适合无特定模块上下文的场景ScopedLoggercreateScopedLogger(baseContext)返回带debug/info/warn/error/event/child方法的对象其中child(context)可派生子上下文event({ level, audit, action, ... })允许构造完整语义事件——logProjectAction与logAuthAction正是该姿势的高层封装。配置参数速查日志配置集中在config.ts全部通过环境变量驱动环境变量默认值说明LOG_UNIFIED_ENABLEDtrue总开关1/true/yes/on视为开启LOG_LEVELINFO全局级别取DEBUG/INFO/WARN/ERROR非法值回落 INFOLOG_DEBUG_ENABLEDfalseDEBUG 独立开关默认关闭避免例行查询噪音LOG_AUDIT_ENABLEDtrueaudit 通道总开关LOG_SERVICEwaoowaoo事件service字段值LOG_REDACT_KEYS逗号分隔的 14 个敏感键默认覆盖password,token,apikey,authorization,cookie,secret,credential,signature,bearer,jwt,privatekey,accesskey,sessiontokenLOG_FILE_MAX_BYTES209715200200MB单文件轮转阈值LOG_FILE_MAX_GENERATIONS10轮转保留代数默认约 2GB级别权重在config.ts中定义DEBUG10、INFO20、WARN30、ERROR40满足权重 配置级别权重才输出DEBUG 还需单独开启debugEnabled。默认 INFO 级别确保正常路径事件可见——这正对应文档踩过的坑中默认曾为 ERROR 导致观测归零的历史教训。时间戳在core.ts按北京时间UTC8生成 ISO 字符串形如2026-10-08T00:23:03.00008:00。落盘副本原子 rename 轮转与有界下载file-writer.ts 维护唯一的便利副本logs/app.log设计约束是与数据库共享同一块盘因此无上限增长会以磁盘写满收场——默认 200MB × 10 代约 2GB需要更长历史时调大LOG_FILE_MAX_BYTES即可。轮转基于rename 而非 read-modify-write当前文件超过阈值时代数依次后移app.log.N-1 → app.log.Napp.log → app.log.1丢弃最老一代其他仍持有旧路径的进程会跟随 rename 继续追加不丢当前行——这正是文档中曾按 project 分文件、多进程 read-modify-write 产生竞态丢行事故的防复发设计。文件写入刻意做成 fire-and-forget写失败只console.error提示绝不崩溃应用。模块在 import 期保持 Edge-safeNode 原生模块node:fs、node:path、process.cwd()通过new Function间接动态 import 延迟到写时加载绕过 Next.js 静态分析器的 Edge Runtime 检查。管理端下载走readAllLogs()完整历史留在磁盘下载只返回最近整文件窗口直到DOWNLOAD_MAX_BYTES 100MB内存预算耗尽按时间顺序拼接返回保证字符串始终内存有界。浏览器端异常上报只承担诊断前端未知异常上报有独立链路client-reporter.ts 作为浏览器端单例负责把window error/unhandledrejection/ React render error / 显式调用投递到POST /api/client-log。硬约束包括相同messagestack在 60 秒窗口内只上报一次去重离线时直接丢弃不排队、不重放任何内部失败静默吞掉上报绝不反过来破坏页面。字段全部截断message 2000、stack 8000、URL 1000、userAgent 400、id 128 字符。服务端入口route.ts做三层防护限流登录用户按 userId 60 秒 30 条匿名来源按 IP 60 秒 10 条更严因为错误边界同样覆盖登录页/落地页匿名页面前端崩溃不能因强制登录而 100% 丢失体量校验单条上报体上限 16KB脱敏正则清洗敏感键值对token/authorization/cookie/password/secret/api_key等、Bearer 与 JWTURL 剥离 query/hash浏览器插件chrome-extension://等来源直接丢弃。值得注意的字段纪律客户端上传的 requestId/projectId 未经服务端校验只进入 detailsclientRequestId/clientProjectId不写入日志上下文的权威 requestId/projectId 列——与 LG-02禁止把 identity 埋进 details形成对称信任边界的差异决定了哪些字段可以进入顶层列。已知架构债getLogContext() 被业务正确性复用文档明确警告getLogContext()的执行上下文目前被业务正确性复用已超出观测职责。源码可验证在计费服务的withSyncBillingCore中getLogContext().taskId直接决定是否跳过同步计费协议Task billing is owned by Task creation Terminal Service同文件 L741 的生成函数也有同样的短路判定。此外llm-runtime.ts 与 provider-invocation.ts 都从该上下文读取 taskId 参与幂等与 at-most-once fence 判定。因此日志上下文丢失会直接改变计费与重提交行为。在拆分出独立 execution-context 模块之前不得以日志与正确性无关为由重构上下文传播行为——withLogContext/setLogContext的语义目前是双刃剑既服务于观测关联也承载着业务正确性。踩过的坑与防复发设计文档记录的每一条事故仓库都有对应的现实现制日志级别默认 ERROR → 观测归零默认改为 INFO解析失败回落 INFO审计事件独立于级别config.tsLLM 输出全文入日志 → 第二事实源只记 ID/摘要/耗时唯一出口统一脱敏LG-03按 project 分文件 → 多进程竞态丢行全局单文件 append 原子 rename 轮转LG-01认证审计 25 处调用错位传参 → userId 恒空从位置参数改为结构化入参logAuthAction的具名参数签名自研 console 扫描脚本未接 CI、静默降级改由 ESLint 统一裁决豁免名单精确到文件LG-06源码字符串存在性脚本因没有独立 oracle 一并删除LG-07共享 poll 入口每条查询写 INFO、Worker 重复写进度 → 交错刷屏例行查询不是业务事实pending 只记 DEBUG、阶段变化才 INFOcore.ts 中的SUPPRESSED_LOG_ACTIONS如worker.progress.stream为高频进度流提供了事件级抑制兜底——文档指出该契约随后在另一 provider 的状态查询处换形式复发过一次提醒任何新接 Provider 轮询逻辑时都必须复检。结语一份可执行、可审计、可告警的日志契约waoowaoo 的日志与可观测性设计证明把日志是什么写成八条编号不变量LG-01~LG-08比堆砌实现细节更能抵御事故复发。stdout 单行 JSON 作为唯一权威流身份/摘要/耗时作为记录底线audit 旁路级别过滤、alert.*前缀承载告警路由、ESLint 独裁 no-console再加上 AsyncLocalStorage 的上下文传播——这套组合既是自托管部署下可运维的观测底座也是计费、幂等与失败治理赖以生存的执行上下文载体。如需在业务代码中新增日志或审计事件建议对照模块文档逐条复核是否触犯不变量再参照semantic.ts与client-log 入口选择正确的语义封装。赞分享【免费下载链接】waoowaoo首家工业级全流程 AI 影视生产平台。Industry-first professional AI Agent platform for controllable film video production. From shorts to live-action with Hollywood-standard workflows.项目地址https://gitcode.com/gh_mirrors/wa/waoowaoo点击查看免费下载相关推荐Generamba高级功能钩子Hooks和自定义动作详解Generamba高级功能钩子Hooks和自定义动作详解 Generamba 作为一款强大的Xcode代码生成器不仅能够快速生成VIPER模块还提供了YouTube.js 日志体系剖析warnOnce 单次警告机制与 Log 命名空间全解读YouTube.js 日志体系剖析warnOnce 单次警告机制与 Log 命名空间全解读 导读 warnOnce 是 YouTube.jsInnerTub后端Cloudflare Tail Workers 实战指南为 Cloudflare Workers 构建实时可观测性与日志管道Cloudflare Tail Workers 实战指南为 Cloudflare Workers 构建实时可观测性与日志管道 本文档来自本仓库 Codex S人工智能AI 技能AI 插件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考