1
0

feat: 新增本机 CPU checker

- 新增 type: cpu checker,基于 os.cpus() 两次快照计算 CPU 使用率
- 配置项:sampleDuration(默认 1s)、includePerCore(默认 false)
- expect 字段:usagePercent、idlePercent、maxCoreUsagePercent、minCoreUsagePercent、durationMs
- idlePercent 与 usagePercent 互补恒等于 100,百分比范围 0-100
- logicalCoreCount 仅输出到 observation,不作为 expect 字段
- 不暴露 userPercent / systemPercent
- 语义校验禁止 sampleDuration >= timeout
- 支持 AbortSignal 超时取消
- 完整测试覆盖:schema、validate、normalize、resolve、calculate、execute、expect、config-loader
- 新增用户文档 docs/user/checkers/cpu.md
- 更新 checker 索引、配置类型列表、示例配置和 schema
This commit is contained in:
2026-05-26 22:34:57 +08:00
parent f38286d74d
commit c2dcfab80c
22 changed files with 1839 additions and 3 deletions

View File

@@ -2270,6 +2270,82 @@ targets:
);
});
test("解析最简 cpu 配置", async () => {
const configPath = join(tempDir, "minimal-cpu.yaml");
await writeFile(
configPath,
`targets:
- id: "local-cpu"
type: cpu
cpu: {}
`,
);
const config = await loadConfig(configPath);
expect(config.targets).toHaveLength(1);
const t = config.targets[0]! as Record<string, unknown>;
expect(t["type"]).toBe("cpu");
expect((t["cpu"] as Record<string, unknown>)["sampleDurationMs"]).toBe(1000);
expect((t["cpu"] as Record<string, unknown>)["includePerCore"]).toBe(false);
expect(t["group"]).toBe("default");
expect(t["intervalMs"]).toBe(30000);
expect(t["timeoutMs"]).toBe(10000);
});
test("解析 cpu expect 配置", async () => {
const configPath = join(tempDir, "cpu-expect.yaml");
await writeFile(
configPath,
`targets:
- id: "local-cpu"
type: cpu
cpu:
sampleDuration: "2s"
includePerCore: true
expect:
usagePercent: { lte: 85 }
idlePercent: { gte: 15 }
maxCoreUsagePercent: { lte: 95 }
durationMs: { lte: 3000 }
`,
);
const config = await loadConfig(configPath);
expect(config.targets).toHaveLength(1);
const t = config.targets[0]! as Record<string, unknown>;
expect((t["cpu"] as Record<string, unknown>)["sampleDurationMs"]).toBe(2000);
expect((t["cpu"] as Record<string, unknown>)["includePerCore"]).toBe(true);
expect((t["expect"] as Record<string, unknown>)["usagePercent"]).toEqual({ lte: 85 });
});
test("cpu expect 未知字段抛出错误", async () => {
await expectConfigError(
"cpu-unknown-expect.yaml",
`targets:
- id: "local-cpu"
type: cpu
cpu: {}
expect:
logicalCoreCount: { gte: 4 }
`,
"expect.logicalCoreCount 是未知字段",
);
});
test("cpu sampleDuration >= timeout 抛出错误", async () => {
await expectConfigError(
"cpu-sample-too-long.yaml",
`targets:
- id: "local-cpu"
type: cpu
timeout: "1s"
cpu:
sampleDuration: "5s"
`,
"sampleDuration 必须小于 timeout",
);
});
describe("logging 配置", () => {
test("logging 全部缺省时使用默认值", async () => {
const configPath = join(tempDir, "logging-default.yaml");