Skip to content

fix(wiki-export): 启动期以进度与统计取代逐条 blob 日志刷屏; - #1119

Merged
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/quiet-blob-startup-logs
Sep 2, 2026
Merged

fix(wiki-export): 启动期以进度与统计取代逐条 blob 日志刷屏;#1119
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/quiet-blob-startup-logs

Conversation

@ThreeFish-AI

@ThreeFish-AI ThreeFish-AI commented Sep 2, 2026

Copy link
Copy Markdown
Owner

背景

  • 本次变更要解决的问题:启动期 Wiki 内容同步(cli.shsync-wiki-content.shexport_wiki_content.py)实测输出 412 行,其中 403 行是 blob_download_completed,把仅有的汇总行彻底淹没,用户只想看到「执行进度 + 统计结果」。
  • 根因为两层,只修一层无效
    1. postgres_client 对每次 blob 读取打 INFO —— 这是 per-IO trace 而非业务事件;
    2. export_wiki_content.py 从未调用 configure_logging,也不经 engine.bootstrap(全仓唯一在 import 期配置日志之处),structlog 停留在出厂默认make_filtering_bound_logger(NOTSET) 不过滤 DEBUG + stock ConsoleRenderer。故 NE_LOG_LEVEL 对该脚本此前完全失效,仅降级日志一行都不会少。
  • 诊断证据(可在原始日志中直接读出):_name=negentropy.storage.postgres 键泄漏(项目的 add_logger_name 处理器本会 pop 掉它),以及 logging.level: INFO 配置下仍打印的 [debug] disposer_registered
  • 关联上下文:logging/core.pyconfigure_logging 唯一入口)、engine/bootstrap.py(唯一既有调用点)。

核心变更

  • 读路径 per-IO trace 降级postgres_client.pyblob_download_completedblob_download_range_completed 由 info 改 debug(后者是 PDF 阅读器每次 Range 请求刷一行,为后端运行期最高频同类噪音)。语义分界:读是 trace,写是审计事件 —— blob_upload_completed / blob_delete_completed 与全部 error 分支保持不变
  • 导出 CLI 接入项目统一日志:新增 scripts/_logging.py::configure_script_logging(),把 settings.log_* 映射到项目唯一日志入口,不 import 重型 engine 包(避免拉起 ADK/LiteLLM 副作用)。export_wiki_content.py重型 import 之前调用(顺序即正确性:db_session 等在 import 期即打 disposer_registered),并将末尾 print 汇总改为结构化事件(configure_logging 会以 StreamToLogger 接管 sys.stdout,顺应该设计而非与之对抗)。
  • 补有界进度日志wiki_export_service 增加 wiki_export_started / wiki_export_publication / wiki_export_progress,进度按 step = max(1, total // 10) 节流并强制在末条发一次 —— 每 publication 恒定约 10 行,输出量与语料规模解耦。原 continue 改写为 else 分支以保证进度不被跳过(语义等价)。
  • 修正汇总统计口径wiki_export_done 原用 len(pubs),漏计注入的合成 docs publication,导致同一次运行日志报 publications=1 而 CLI 汇总报 2;改用 len(result.publications),与 to_dict() 对齐。
  • 刻意不做:不加资产去重缓存 —— 已核对日志,403 条 URI 全部互异,无重复下载可消除(YAGNI)。

风险与回滚

  • 主要风险
    1. blob 读日志降级后,线上排查失去逐条 INFO 线索 —— 已缓解:明细未删除,NE_LOG_LEVEL=DEBUG 可完整取回;且全仓核实这两个事件零测试、零文档、零看板引用(各仅 1 处定义)。
    2. configure_logging 会重置 root logger、拦截三方 logger 并接管 stdout/stderr —— 短命 CLI 中均为预期行为;run_scriptprint("Error: ...", file=sys.stderr) 会变成日志行,仍可见,且 cli.sh 依赖的是退出码而非该文本,行为不变。
    3. 爆炸半径已收敛:其余 7 个 scripts/*.py 未改动_logging.py 仅为其留好接入口。
  • 回滚方式:单个 commit,git revert 即可完整回退;无 DB 迁移、无配置变更、无接口契约变更。

验证证据

  • 单元测试:新增回归用例 test_progress_bounded_and_summary_counts_docs_pack,复用既有免 DB 夹具 + structlog.testing.capture_logs,断言 ①进度日志有界(50 entry → 10 条)②末条覆盖最后一个 entry ③publications == 2。已实测改前失败(assert 1 == 2)、改后通过
  • 集成测试tests/unit_tests/knowledge + tests/integration_tests/storage 全量 1086 passed;pre-commit(ruff lint + format 等)全绿。
  • E2E/Workflow:实跑真实启动链路 bash scripts/sync-wiki-content.sh —— 日志 412 → 18 行blob_download_completed 403 → 0_name= 泄漏 0,格式已与后端一致:
wiki_export_started publications=1 out_dir=...
wiki_export_publication slug=wiki entries=25
wiki_export_progress slug=wiki entries_done=2  entries_total=25 assets=6
...(共 13 条,assets 累加至 403)
wiki_export_docs_pack slug=negentropy entries=115
wiki_export_done publications=2 entries=135 graphs=1 assets=403 files=547
wiki_export_cli_done publications=2 entries=135 graphs=1 files=547 out_dir=...
  • 门控有效性NE_LOG_LEVEL=DEBUG403 行明细完整取回 —— 同时证明该环境变量对此脚本终于生效。
  • 产物零回归:改前/改后各跑一次全量导出并 diff -r —— 547 文件 / 403 assets 逐字节一致,唯一差异是 index.jsongenerated_at 时间戳。

影响范围

  • 前端:无。
  • 后端storage/postgres_client.py(2 行日志级别)、knowledge/lifecycle/wiki_export_service.py(进度日志 + 统计口径)。PDF 预览 Range 端点的逐请求 INFO 一并降噪。
  • GitHub Actions / 文档:CI wiki-content-export.ymlbake_assets=false 的 URL 重写分支,本就无 blob 日志,仅受益于格式统一;publish-wiki-pages.sh / build-wiki-local.sh 调用同一脚本,一处改动覆盖三条噪音路径,无需另改。

Next Best Action

  • 其余 7 个 apps/negentropy/scripts/*.py 仍是「出厂默认 structlog」状态(同样 NE_LOG_LEVEL 失效、_name= 泄漏),_logging.py 已留好接入口,可另开 PR 统一接入。
  • 可考虑把「读=debug / 写=info」的 blob 日志分级口径沉淀进 docs/.agents/,避免后续新增存储后端时重蹈逐条 IO 打 INFO。

🤖 Generated with Claude Code

启动期 Wiki 内容同步(cli.sh → sync-wiki-content.sh → export_wiki_content.py)
实测输出 412 行,其中 403 行为 blob_download_completed,把仅有的汇总行淹没。

根因为两层,只修一层无效:
1. postgres_client 对每次 blob 读取打 INFO——这是 per-IO trace 而非业务事件;
2. export_wiki_content.py 从未调用 configure_logging,也不经 engine.bootstrap,
   structlog 停留在出厂默认(不过滤 DEBUG + stock 渲染器,故 _name 键泄漏、
   格式与后端不一致),NE_LOG_LEVEL 对该脚本完全失效——仅降级日志不会少一行。

变更:
- postgres_client: blob_download_completed / blob_download_range_completed 降为
  debug(读是 trace);upload / delete 保持 info(写是审计事件),error 分支不动;
- 新增 scripts/_logging.py::configure_script_logging(),把 settings.log_* 映射到
  项目唯一日志入口,不 import 重型 engine 包;export_wiki_content.py 在重型 import
  之前调用(顺序即正确性),并将末尾 print 汇总改为结构化事件;
- wiki_export_service: 补 started / publication / progress 日志,进度按
  step=max(1, total//10) 节流,每 publication 恒定约 10 行,输出量与语料规模解耦;
- 修正 wiki_export_done 的 publications 口径:len(pubs) 漏计注入的 docs pack,
  致同一次运行日志报 1 而 CLI 汇总报 2,改用 len(result.publications)。

验证:实跑 sync-wiki-content.sh,日志 412 → 18 行、blob 行 403 → 0、_name 泄漏 0;
NE_LOG_LEVEL=DEBUG 下 403 行明细可完整取回(未删除,仅门控);产物零回归——
547 文件 / 403 assets 与改前逐字节一致,diff 仅 index.json 的 generated_at 不同;
新增回归用例(capture_logs 断言进度有界 + publications 计数),改前失败改后通过;
knowledge 单测与 storage 集成测试 1086 passed。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
…为静默失败;

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
@ThreeFish-AI
ThreeFish-AI merged commit 17083bd into feature/1.x.x Sep 2, 2026
4 checks passed
@ThreeFish-AI
ThreeFish-AI deleted the ThreeFish-AI/quiet-blob-startup-logs branch September 2, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant