shared worker 是跨标签页日志聚合与调度的核心机制,通过结构化消息入队、分优先级宏观排队、indexeddb 持久化及指数退避防雪崩,确保日志不丢、不乱、可追溯。

Shared Worker 是目前浏览器中唯一能天然聚合多标签页日志、实现宏观排队与集中调度的机制。它不依赖页面状态,也不受后台冻结影响,适合做跨窗口的日志收口中枢——所有日志不上报、不丢弃、不乱序,而是先入队、再择机批量发送。
日志必须统一走 Shared Worker 入口
每个页面禁止直接调用 fetch 或 console.log 上报日志。正确做法是:
- 页面通过
worker.port.postMessage({ type: 'log', level: 'error', msg: 'API timeout', traceId: 'abc123' })提交结构化日志 - Shared Worker 脚本中监听所有端口消息,将日志对象推入一个全局 FIFO 队列(如
const queue = []) - 队列不设上限,但需限制内存占用——例如超过 500 条时自动截断最旧的 100 条(避免 OOM)
宏观排队:按业务优先级 + 时间窗口分批提交
“宏观排队”不是简单等满再发,而是结合时效性与重要性做分层调度:
- 错误类日志(error / fatal):立即触发上报,不等待、不合并,保证问题可追溯
- 警告类(warn):缓存 2 秒,若期间同 traceId 再次出现,合并为一条并增加 count 字段
- 信息类(info / debug):按 10 秒窗口聚合,最多打包 30 条,以减少请求数量
- 所有上报请求都带
X-Log-Batch-ID和时间戳,便于服务端对齐和去重
容错与持久化:断网时不丢日志
网络不可用时,日志不能堆积在内存里等恢复——必须落地再读取:
- Shared Worker 中用 IndexedDB(非 localStorage)持久化待发日志,表名
pending_logs,主键为自增 ID - 每次成功上报后,用事务删除对应记录;失败则标记
retryCount,超 3 次后自动归档到failed_logs - Worker 启动时主动检查 DB,把未发日志重新载入内存队列,实现“断电续传”效果
防雪崩:服务端限流下的本地退避
当服务端返回 429(Too Many Requests)时,不能所有页面一起重试:
- Shared Worker 收到 429 后,暂停全部上报,并启动指数退避定时器(1s → 2s → 4s)
- 退避期间新进日志继续入队,不丢弃;但只允许每 5 秒最多发一次试探请求
- 一旦某次请求成功,立即清空退避状态,并广播给所有页面:「日志通道已恢复」











