FinDataHub
9e05a153c3
feat(observability): 采集器记录终止信号与线程堆栈,补上崩溃排查的最后一块盲区
背景
----
部署 faulthandler 崩溃捕获后实测:`collector-crash.log` **一直是空的**。
这说明采集器**不是 Python 异常退出**,而是被**外部信号终止** ——
faulthandler 默认只接管 SIGSEGV/SIGABRT/SIGBUS 这类致命信号,**不覆盖 SIGTERM**。
于是应用日志里只有一句"采集器异常停止","谁终止了它、当时卡在哪一步"依旧无从判断。
改动
----
`_install_crash_handlers()` 增加 SIGTERM/SIGINT 处理:
- 记录信号名、时间、pid
- **记录所有线程的当前堆栈**(这是区分"被外部终止"与"自己卡死"的关键证据)
- 记录后恢复 SIG_DFL 再自杀,保持原有退出语义(父进程仍观测到相同退出信号)
- 仅在常驻模式(`start`)安装,不影响 stop/status 等短命令
验证
----
新增跨进程用例 `TestTerminationSignalLogging`:子进程装处理器 → 父进程发 SIGTERM
→ 断言日志含信号名与线程堆栈。
**信号处理必须在子进程验证**:pytest 主进程装上处理器后向自己发信号会直接终止测试运行。
已证伪:移除处理器安装后该用例报 `assert '收到终止信号' in ''`。
运行态说明
----------
已同步部署位并重启采集器(新 PID 22361)使处理器生效,采集正常(30 分钟 136 条)。
另记录一条观察:**App 的自动恢复不覆盖"主动 stop"** —— 用 CLI 正常停止采集器后
75 秒内未被自动拉起(这是合理行为:不该重启用户主动停的服务),
故主动停后需手动启动。
回归
----
Scripts/bin 214(+1)、core 121、tushare 174、akshare 183、kuaixun 410 = 1102 passed
2026-09-19 08:46:10 +08:00
..
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-19 00:27:21 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-19 08:46:10 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00
2026-09-18 22:37:32 +08:00