docs
形态:一个 C++20 可执行文件(采集 + 检测 + 存储 + HTTP + 报告)+ 一个独立的 Python 因果分析服务 + 静态大屏 + 单文件 SQLite。 三条采集通路各自独立:常态化宏观指标、内核异常事件、阈值触发的深度快照。
采集分三面,互不依赖——这是本项目与”一个窗口里什么都有”的传统监控最大的区别:
plane/metrics
/proc
plane/events
plane/snapshot
主机异常检测(detect/)只读指标面,产出 incident 时间窗——它回答”哪段时间不正常”, 不回答方向、不回答类型、不回答根因;也不触发任何快照(两条通路正交,有专门验收项钉这条)。 实现是绝缘参考 + 双通道累积和监视器:参考层(Huber 位置 + 有界影响尺度 + 日周期时段槽)给出”正常水平与正常波动”, 检测层用 EWMA(抓大阶跃)与 CUSUM 对(抓小而持续的位移)双通道判定, 门限由误报预算在启动时按 ARL 目标解出(M×2×T_week/ARL0 ≤ 1 次假主机事件/周),之后与数据彻底解耦。
detect/
M×2×T_week/ARL0 ≤ 1
因果分析(src/causal,独立 Python 服务,无写库权)不是常态跑,而是事件触发的一次分析: incident 闭合 → 执行器把它窗口内(前 60 s / 后 10 s)的全部已采集数据打成 ekd.panel.v1 数据包 → POST 给分析服务 → 结论作为一条 kCausal 记录落库 → 报告端点引用它(不复述、不改写)。 结论分三级(fact / temporal / hypothesis),只有拿到干预或结构机制证据才允许使用”因果”字样; 样本不足、无幸存变更、事件过稀疏、输入被截断 → 一律如实降级为 insufficient 并写出缺口码,root_causes 为空数组。
src/causal
ekd.panel.v1
kCausal
fact
temporal
hypothesis
insufficient
root_causes
结构化报告(report/)把 incident 与窗口内的事件/快照装配成 anomaly_type / objects / key_metrics / window / evidence / suspected_cause / causal / basis / gaps。 suspected_cause 是规则推断(字段里明写 basis=rule_inference);causal 块只放分析服务的原样结论, 服务不可达时写 unavailable + 原因,并在 gaps 里明说”未经因果确认,不得据此认定根因”。
report/
anomaly_type / objects / key_metrics / window / evidence / suspected_cause / causal / basis / gaps
suspected_cause
basis=rule_inference
causal
unavailable
gaps
state
observed / no_events / warming_up / gated / degraded / unavailable / held
RecordSink
src/ ├── ekd/ C++20 单二进制 │ ├── include/ekd/ 对外契约(唯一事实源):contracts / platform / probe / record / config / store │ ├── src/ │ │ ├── core/ 时钟、日志、契约的 JSON 序列化(字段名的唯一来源) │ │ ├── config/ JSON 配置(支持 // 注释)解析 + 语义校验 │ │ ├── probe/ 框架:单注册表 + 三角色 + 每探针一线程 │ │ ├── bpf/ 加载·挂载·ringbuf·perf 采样器·符号化;prog/ 每探针一个 BPF 对象 │ │ ├── collect/ /proc 读取器、cgroup v2 解析、进程扫描、差分器 │ │ ├── plane/metrics/ 26 项指标 + 内存环 + 滚动汇总 │ │ ├── plane/events/ 8 类内核异常事件 │ │ ├── plane/snapshot/ 6 类深度快照 + 触发闸(冷却/单飞/并发) │ │ ├── detect/ ir_dcm(检测器本体)+ detect_runner(接线层) │ │ ├── store/ SQLite(WAL) 单写路径 │ │ ├── api/ HTTP + SSE(只服务自制大屏) │ │ ├── report/ 结构化报告 · Panel 组装 · 因果服务客户端 · 因果执行器 │ │ └── main.cpp 组合根:有序启动步骤 + 逆序清理 │ ├── web/index.html 自制大屏(单文件、零外部依赖、离线可用) │ ├── tools/ 逐阶段验收脚本(s1..s7)· arl_check.py · perf_check.sh │ └── docs/ REFACTOR_PLAN.md(设计权威)· ACCEPTANCE.md(验收留档) └── causal/ 因果分析服务(Python:仅 numpy + scipy + stdlib) ├── service.py POST /analyze · GET /health ├── cli.py 离线跑同一流水线(复核用) ├── panel.py audit.py engine.py falsify.py route.py └── tests/ 合成数据用例(含扫描零校准回归)
# 构建(依赖全部随源码内置:spdlog / nlohmann-json / cpp-httplib / libbpf 1.8) cmake -S src/ekd -B src/ekd/build -G Ninja && ninja -C src/ekd/build # 单元测试(含检测器 54 项断言) ctest --test-dir src/ekd/build # 配置自检 src/ekd/build/ekd --check-config --config src/ekd/ekd.json # 只跑指标面与检测面(不需要 root) src/ekd/build/ekd --config src/ekd/ekd.json --port 8899 # 全量(事件面与快照面需 root 或 CAP_BPF) sudo src/ekd/build/ekd --config src/ekd/ekd.json --port 8899 # 因果分析服务(默认不接线:ekd.json 里 causal.port = 0) python3 src/causal/service.py --port 9400 # 接线:把 causal.port 改成 9400(或任何已监听端口)后重启 ekd # 离线复核:python3 src/causal/cli.py analyze --panel <panel.json> # 大屏 # 浏览器打开 http://127.0.0.1:8899/ ;点击 incident 行查看结构化报告(含因果结论)
逐阶段脚本,每项都判 PASS/FAIL/SKIP 并打印证据(数字、命令行、返回体),需要 root 的项自动提权:
bash src/ekd/tools/s1_accept.sh # 框架 + 1 指标 + 1 事件 + 1 快照 + SQLite + 大屏取数 bash src/ekd/tools/s2_accept.sh # 26 项指标 + 滚动汇总 bash src/ekd/tools/s3_accept.sh # 8 类内核事件 bash src/ekd/tools/s4_accept.sh # 6 类深度快照 bash src/ekd/tools/s5_accept.sh # 检测 → incident 时间窗(含"检测不触发快照") bash src/ekd/tools/s6_accept.sh # 结构化报告 bash src/ekd/tools/s7_accept.sh # 因果端到端(含服务不可达负例与重启幂等) # 阈值口径的独立复算(两套独立机制互证:马尔可夫链网格解 vs 蒙特卡洛) python3 src/ekd/tools/arl_check.py --solve --metrics 26 # 开销实测(检测面开/关对照) bash src/ekd/tools/perf_check.sh 120
当前实测状态与未完成项见 src/ekd/docs/ACCEPTANCE.md (七个阶段全绿;多架构 QEMU 未执行,方案见 REFACTOR_PLAN.md §10)。
src/ekd/docs/ACCEPTANCE.md
REFACTOR_PLAN.md
CAP_BPF/CAP_PERFMON/CAP_SYS_ADMIN
src/ekd/docs/REFACTOR_PLAN.md
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
EKD · 基于 eBPF 的系统异常观测与根因定位工具
设计主张
采集分三面,互不依赖——这是本项目与”一个窗口里什么都有”的传统监控最大的区别:
plane/metrics/proc)plane/eventsplane/snapshot主机异常检测(
detect/)只读指标面,产出 incident 时间窗——它回答”哪段时间不正常”, 不回答方向、不回答类型、不回答根因;也不触发任何快照(两条通路正交,有专门验收项钉这条)。 实现是绝缘参考 + 双通道累积和监视器:参考层(Huber 位置 + 有界影响尺度 + 日周期时段槽)给出”正常水平与正常波动”, 检测层用 EWMA(抓大阶跃)与 CUSUM 对(抓小而持续的位移)双通道判定, 门限由误报预算在启动时按 ARL 目标解出(M×2×T_week/ARL0 ≤ 1次假主机事件/周),之后与数据彻底解耦。因果分析(
src/causal,独立 Python 服务,无写库权)不是常态跑,而是事件触发的一次分析: incident 闭合 → 执行器把它窗口内(前 60 s / 后 10 s)的全部已采集数据打成ekd.panel.v1数据包 → POST 给分析服务 → 结论作为一条kCausal记录落库 → 报告端点引用它(不复述、不改写)。 结论分三级(fact/temporal/hypothesis),只有拿到干预或结构机制证据才允许使用”因果”字样; 样本不足、无幸存变更、事件过稀疏、输入被截断 → 一律如实降级为insufficient并写出缺口码,root_causes为空数组。结构化报告(
report/)把 incident 与窗口内的事件/快照装配成anomaly_type / objects / key_metrics / window / evidence / suspected_cause / causal / basis / gaps。suspected_cause是规则推断(字段里明写basis=rule_inference);causal块只放分析服务的原样结论, 服务不可达时写unavailable+ 原因,并在gaps里明说”未经因果确认,不得据此认定根因”。设计红线(违反即返工)
state(observed / no_events / warming_up / gated / degraded / unavailable / held)。 读不到不能填 0 冒充正常,也不能当成”没有异常”。检测器对”整段缺席”的指标按已知名册记账, 对”尺度估不出来”的指标不判定(不可评 ≠ 正常)。RecordSink入队,由唯一写线程落库。unavailable+ 原因)。目录
构建与运行
验收
逐阶段脚本,每项都判 PASS/FAIL/SKIP 并打印证据(数字、命令行、返回体),需要 root 的项自动提权:
当前实测状态与未完成项见
src/ekd/docs/ACCEPTANCE.md(七个阶段全绿;多架构 QEMU 未执行,方案见REFACTOR_PLAN.md§10)。环境
CAP_BPF/CAP_PERFMON/CAP_SYS_ADMIN(仅事件面与快照面需要;指标面与检测面读/proc即可,可非 root 运行)。src/ekd/docs/REFACTOR_PLAN.md。REFACTOR_PLAN.md§10(未执行)。