Fix all-mode workload attribution and final evidence
SysWatch 是面向 Linux 6.6+ 的一次性系统异常观测与诊断工具。它以 C++17、libbpf 和 eBPF CO-RE 在固定 15 秒 competition 窗口内同时覆盖 syscall、CPU、块 I/O、内存和 futex 五个 collector,并输出结构化 DiagnosisReport 与数值 evidence。外部评测对 pressure/control 的 anomaly type、root-cause code、target 和 evidence 做精确机器判定;all-mode 最终验收标准为 24/24 PASS(12 TP + 12 TN)、零 FAIL/SKIP/INVALID 且 cleanup 全空。
DiagnosisReport
SysWatch 提供可复核的异常分类和数值证据,不是持续事件追踪器。热点信号表示“值得继续调查”,不自动等价于系统资源饱和或已证明的因果关系。
syscall
cpu
io
major:minor
memory
/proc
lock
所有 collector 都将采集结果归一化为 MetricSample;规则层只消费指标,报告层不直接读取 BPF map。这使采集、判定和展示可以分别测试与审计。
MetricSample
/sys/kernel/btf/vmlinux
当前实机验证环境为 openKylin 2.0 SP2(nile)、Linux 6.6.0-19-generic、x86_64。arm64 与跨机器可重复性尚未验证。
6.6.0-19-generic
x86_64
./scripts/check-env.sh make clean make BPFTOOL=/path/to/a/working/bpftool make test
构建成功后生成 ./syswatch 和 ./syswatch-workload。
./syswatch
./syswatch-workload
sudo -n ./syswatch \ --collect all \ --duration 15 \ --threshold-profile competition \ --output markdown \ --metrics-output /var/tmp/syswatch-metrics.json \ > /var/tmp/syswatch-report.md
该命令会产生三类输出:
/var/tmp/syswatch-report.md
--metrics-output
退出码为 0 表示所有请求的 collector 成功,1 表示至少一个 collector 失败,130 表示采集被取消。失败时仍会先输出可用的 partial report,再通过 stderr 给出失败原因。
0
1
130
Usage: ./syswatch [--duration SECONDS] [--interval SECONDS] [--collect TYPE] [--output json|markdown] [--threshold-profile default|competition] [--metrics-output PATH] [--target-pid PID] [--target-object OBJECT] [--cgroup PATH] [--help]
--collect
all
--duration
--interval
--output
json
markdown
--threshold-profile
default
competition
--target-pid
--target-object
--cgroup
--help
设备级 I/O 示例:
sudo -n ./syswatch --collect io --duration 10 \ --target-object 252:0 \ --threshold-profile competition \ --output json
--collect all 采用严格的 five-of-five 语义:syscall、CPU、I/O、memory、lock 必须全部成功 start 和 snapshot,且最终输出恰好包含五种 metric kind,命令才返回 0。
--collect all
collector 先在禁用采集的状态下完成加载与 attach,再统一 arm 到同一个未来半开窗口 [start_ns, end_ns)。所有成功样本必须报告该公共窗口;窗口不一致会使对应 collector 失败,不会把各 collector 的最早开始和最晚结束拼接成一个表面上的总窗口。CPU 与 memory 的 proc/cgroup 计数在窗口两端进行有界采样,超过边界偏差预算时拒绝结果。memory 另在公共窗口起止读取任务匿名 RSS 与 CPU 累计 tick,并以 PID starttime、PGID 和 comm 校验同一进程实例;完整的稳定大工作集还必须具有同窗持续 CPU 活动才参与全采集任务归因,轻量父进程或 wrapper 不计入有效工作成员。
[start_ns, end_ns)
综合判断使用确定性的优先级规则,不宣称由相关性推导出因果关系。
futex_hot_lock
syscall_hotspot
excessive_syscall_rate
futex_wait_pressure
none
典型终端输出如下:
综合判断:主要问题=CPU饱和(worker/PID 4242,CPU密集或忙循环) - 次要问题=无 - 伴随信号=syscall热点、futex等待压力 综合判断:未发现资源压力 - 观察信号=syscall热点、futex等待压力 综合判断:未发现达到阈值的异常
中文综合判断只在 stderr 直接连接 TTY 时显示。stderr 被重定向或通过管道传递时,仍保留 syswatch diagnosis: collector=... anomaly_type=... root_cause_code=... 行,但不输出中文综合判断。NO_COLOR 或 TERM=dumb 只关闭颜色。
syswatch diagnosis: collector=... anomaly_type=... root_cause_code=...
NO_COLOR
TERM=dumb
generic FUTEX_WAIT 只能证明等待队列压力,不能识别 mutex owner,因此报告为 futex_wait_pressure。只有样本含 futex_pi_lock_id=,并同时满足等待时长、并发 waiter 与交接等复合条件时,才报告可参与资源问题排序的 futex_hot_lock。collector 报告始终保留原始 anomaly type、root-cause code 和数值 evidence,便于后续关联分析。
FUTEX_WAIT
futex_pi_lock_id=
内核事件 + /proc + cgroup │ ▼ Collectors │ MetricSample ▼ Deterministic Rules │ DiagnosisReport ├──────────────► JSON / Markdown Reporter └──────────────► Scenario Evaluator
仓库主要目录:
. ├── Makefile 构建与测试入口 ├── include/ BPF 与用户态共享 ABI ├── src/bpf/ 五类 eBPF 程序 ├── src/user/ CLI、collector、规则与 reporter ├── tests/ 单元、契约与脚本测试 ├── scripts/ 环境检查、场景和性能证据 runner ├── tools/ 确定性 workload ├── scenarios/ 场景 ground truth ├── examples/ synthetic 报告 fixture └── docs/ 架构、使用、评测与验证文档
I/O 请求通过 insert/issue/complete 关联,并在 per-CPU map 中按设备聚合;用户态负责检查健康状态和合并各 CPU 副本。完整设计与失败语义见架构说明。
外部矩阵必须以 clean commit/tree 和实测 executable identity 绑定唯一 authoritative summary。验收要求 24/24 PASS:12 个 pressure TP、12 个 control TN,零 FAIL/SKIP/INVALID,24 份 cleanup error 列表均为空。
以下四条是评测消费者可见的精确 workload argv;180 秒是 workload 生命期 guard,SysWatch capture 仍固定为 15 秒:
/usr/local/bin/stress-ng --cpu 4 --cpu-method matrixprod --timeout 180s --metrics-brief /usr/local/bin/fio --name=randrw-test --filename=/tmp/fio-test.img --size=4G --rw=randrw --rwmixread=70 --bs=4k --iodepth=64 --numjobs=4 --runtime=180 --time_based --group_reporting /usr/local/bin/stress-ng --vm 4 --vm-bytes 80% --vm-keep --timeout 180s --metrics-brief /usr/local/bin/stress-ng --mutex 8 --timeout 180s --metrics-brief
基础场景会保存运行上下文、workload 日志、原始 metrics、报告和 evaluation。I/O 场景只应在隔离测试机上,针对 runner 拥有或已验证的 null_blk 设备运行:
null_blk
sudo -n python3 scripts/scenarios/run_basic_suite.py \ --syswatch ./syswatch \ --workload ./syswatch-workload \ --ground-truth scenarios/ground-truth.json \ --output-root /var/tmp/syswatch-basic \ --scenario io_pressure
题目 workload 固定使用 /tmp/fio-test.img。本主机 /tmp 只有 2.9 GiB 可用,不能满足安全的 4.5 GiB preflight;自动化主机运行因此使用题目允许的存储替代 ./.local/syswatch-fio-test.img,其仓库文件系统有 7.0 GiB 可用,并保持 4G 与其他 fio 选项完全不变。这是可复现的环境准备,不改变产品或 evaluator 契约。fresh clone 先创建被 .gitignore 覆盖的目录:
/tmp/fio-test.img
/tmp
./.local/syswatch-fio-test.img
.gitignore
mkdir -p .local sudo -n python3 scripts/scenarios/run_external_pressure_suite.py --syswatch ./syswatch --stress-ng /usr/local/bin/stress-ng --fio /usr/local/bin/fio --fio-file ./.local/syswatch-fio-test.img --ground-truth scenarios/external-pressure-ground-truth.json --output-root /var/tmp/syswatch-results/final-commit-20260810-external --scenario all --rounds 3 --collect-mode all
--collect-mode all 让题目八个 pressure/control 场景的每一轮都实际运行一个 syswatch --collect all。runner 将五份原始诊断完整保存为 all-reports.json;pressure 按目标 collector 校验 type/root/target/evidence,control 则检查同轮全部五份报告,任一禁止异常都会判为 FP,而不是只看选中的单份报告。
--collect-mode all
syswatch --collect all
all-reports.json
sudo -n python3 scripts/scenarios/run_all_smoke.py \ --syswatch ./syswatch \ --workload ./syswatch-workload \ --output-root /var/tmp/syswatch-results/final-commit-20260810-all
sudo -n env FIO_BIN=/usr/local/bin/fio BPFTOOL_BIN=./bin/bpftool \ ./scripts/measure-overhead.sh \ --mode io --rounds 3 --duration 30 \ --output-root /var/tmp/syswatch-results/final-commit-20260810-performance
三个待运行的 final 审计目标分别是 /var/tmp/syswatch-results/final-commit-20260810-external、/var/tmp/syswatch-results/final-commit-20260810-all 和 /var/tmp/syswatch-results/final-commit-20260810-performance;README 不预告其 external 计数、strict-all success 或性能数值。每个根只能接受唯一 run,且 summary 必须匹配最终 commit/tree、无 executable drift、authoritative=true、validation_errors=[]。更完整的判定与路径审计见评测说明。性能脚本提供 fio-only、fio + I/O、fio + all 的 A/B/C measurement capability;validity 与 target attainment 分开报告。
/var/tmp/syswatch-results/final-commit-20260810-external
/var/tmp/syswatch-results/final-commit-20260810-all
/var/tmp/syswatch-results/final-commit-20260810-performance
authoritative=true
validation_errors=[]
性能证据脚本可先以 dry-run 检查命令与目录布局;该模式不会加载模块或访问块设备:
DRY_RUN=1 ./scripts/measure-overhead.sh \ --mode io \ --rounds 3 \ --duration 5 \ --output-root /var/tmp/syswatch-overhead-dry-run
--allow-dirty-source 只用于开发排障;它允许 dirty tracked source 开始运行,但会永久把该次输出标记为 non-authoritative,因此不得用于上述三个最终根。
--allow-dirty-source
page_fault_user
Processed 1000001 insn
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
SysWatch
SysWatch 是面向 Linux 6.6+ 的一次性系统异常观测与诊断工具。它以 C++17、libbpf 和 eBPF CO-RE 在固定 15 秒 competition 窗口内同时覆盖 syscall、CPU、块 I/O、内存和 futex 五个 collector,并输出结构化
DiagnosisReport与数值 evidence。外部评测对 pressure/control 的 anomaly type、root-cause code、target 和 evidence 做精确机器判定;all-mode 最终验收标准为 24/24 PASS(12 TP + 12 TN)、零 FAIL/SKIP/INVALID 且 cleanup 全空。核心能力
syscallcpuiomajor:minor聚合,不提供 PID、路径或单请求追踪memory/proc系统指标、进程组匿名 RSS 与同窗 CPU 活动、cgroup v2 与可选 fault telemetrylock所有 collector 都将采集结果归一化为
MetricSample;规则层只消费指标,报告层不直接读取 BPF map。这使采集、判定和展示可以分别测试与审计。快速开始
环境要求
/sys/kernel/btf/vmlinux可读;当前实机验证环境为 openKylin 2.0 SP2(nile)、Linux
6.6.0-19-generic、x86_64。arm64 与跨机器可重复性尚未验证。构建与测试
构建成功后生成
./syswatch和./syswatch-workload。运行完整采集
该命令会产生三类输出:
/var/tmp/syswatch-report.md--metrics-outputMetricSampleJSON 数组,采用原子替换写入退出码为
0表示所有请求的 collector 成功,1表示至少一个 collector 失败,130表示采集被取消。失败时仍会先输出可用的 partial report,再通过 stderr 给出失败原因。CLI 参考
--collectsyscall、cpu、io、memory、lock或all;默认syscall--duration--interval--outputjson或markdown;默认json--threshold-profiledefault或competition;默认default--metrics-output--target-pidall中不用于 I/O--target-objectmajor:minor;all中不再过滤其他 collector--cgroupmemory或all指定 cgroup v2 内存目标--help设备级 I/O 示例:
诊断契约
共享采集窗口
--collect all采用严格的 five-of-five 语义:syscall、CPU、I/O、memory、lock 必须全部成功 start 和 snapshot,且最终输出恰好包含五种 metric kind,命令才返回0。collector 先在禁用采集的状态下完成加载与 attach,再统一 arm 到同一个未来半开窗口
[start_ns, end_ns)。所有成功样本必须报告该公共窗口;窗口不一致会使对应 collector 失败,不会把各 collector 的最早开始和最晚结束拼接成一个表面上的总窗口。CPU 与 memory 的 proc/cgroup 计数在窗口两端进行有界采样,超过边界偏差预算时拒绝结果。memory 另在公共窗口起止读取任务匿名 RSS 与 CPU 累计 tick,并以 PID starttime、PGID 和 comm 校验同一进程实例;完整的稳定大工作集还必须具有同窗持续 CPU 活动才参与全采集任务归因,轻量父进程或 wrapper 不计入有效工作成员。资源异常与观察信号
综合判断使用确定性的优先级规则,不宣称由相关性推导出因果关系。
futex_hot_locksyscall_hotspot/excessive_syscall_ratefutex_wait_pressurenone典型终端输出如下:
中文综合判断只在 stderr 直接连接 TTY 时显示。stderr 被重定向或通过管道传递时,仍保留
syswatch diagnosis: collector=... anomaly_type=... root_cause_code=...行,但不输出中文综合判断。NO_COLOR或TERM=dumb只关闭颜色。Lock 归因边界
generic
FUTEX_WAIT只能证明等待队列压力,不能识别 mutex owner,因此报告为futex_wait_pressure。只有样本含futex_pi_lock_id=,并同时满足等待时长、并发 waiter 与交接等复合条件时,才报告可参与资源问题排序的futex_hot_lock。collector 报告始终保留原始 anomaly type、root-cause code 和数值 evidence,便于后续关联分析。架构
仓库主要目录:
I/O 请求通过 insert/issue/complete 关联,并在 per-CPU map 中按设备聚合;用户态负责检查健康状态和合并各 CPU 副本。完整设计与失败语义见架构说明。
验证状态
最终 all-mode 验收标准
外部矩阵必须以 clean commit/tree 和实测 executable identity 绑定唯一 authoritative summary。验收要求 24/24 PASS:12 个 pressure TP、12 个 control TN,零 FAIL/SKIP/INVALID,24 份 cleanup error 列表均为空。
固定 competition pressure workload
以下四条是评测消费者可见的精确 workload argv;180 秒是 workload 生命期 guard,SysWatch capture 仍固定为 15 秒:
复现验证
基础场景会保存运行上下文、workload 日志、原始 metrics、报告和 evaluation。I/O 场景只应在隔离测试机上,针对 runner 拥有或已验证的
null_blk设备运行:题目 workload 固定使用
/tmp/fio-test.img。本主机/tmp只有 2.9 GiB 可用,不能满足安全的 4.5 GiB preflight;自动化主机运行因此使用题目允许的存储替代./.local/syswatch-fio-test.img,其仓库文件系统有 7.0 GiB 可用,并保持 4G 与其他 fio 选项完全不变。这是可复现的环境准备,不改变产品或 evaluator 契约。fresh clone 先创建被.gitignore覆盖的目录:--collect-mode all让题目八个 pressure/control 场景的每一轮都实际运行一个syswatch --collect all。runner 将五份原始诊断完整保存为all-reports.json;pressure 按目标 collector 校验 type/root/target/evidence,control 则检查同轮全部五份报告,任一禁止异常都会判为 FP,而不是只看选中的单份报告。三个待运行的 final 审计目标分别是
/var/tmp/syswatch-results/final-commit-20260810-external、/var/tmp/syswatch-results/final-commit-20260810-all和/var/tmp/syswatch-results/final-commit-20260810-performance;README 不预告其 external 计数、strict-all success 或性能数值。每个根只能接受唯一 run,且 summary 必须匹配最终 commit/tree、无 executable drift、authoritative=true、validation_errors=[]。更完整的判定与路径审计见评测说明。性能脚本提供 fio-only、fio + I/O、fio + all 的 A/B/C measurement capability;validity 与 target attainment 分开报告。性能证据脚本可先以 dry-run 检查命令与目录布局;该模式不会加载模块或访问块设备:
--allow-dirty-source只用于开发排障;它允许 dirty tracked source 开始运行,但会永久把该次输出标记为 non-authoritative,因此不得用于上述三个最终根。已知限制
page_fault_user等可选 telemetry 缺失时,memory collector 可能只能给出系统级归因。Processed 1000001 insnverifier 故障及解决过程记录在 I/O verifier 问题记录。文档