Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
73 lines
2.5 KiB
TypeScript
73 lines
2.5 KiB
TypeScript
import { z } from "zod";
|
||
import { Timestamp } from "./common.ts";
|
||
|
||
// 资源监控(界面第二轮 V 线,参考 MoviePilot 仪表盘的 CPU / 内存 / 网络组件):
|
||
// api 进程每 5 秒读一次 /proc 与 cgroup v2,采样只放内存(保留 6 小时,进程重启后从头攒)。
|
||
// 容器里优先用 cgroup(本容器的 CPU 占用、内存、磁盘读写),取不到时退回 /proc 整机口径;都取不到的字段为 null。
|
||
|
||
/** 采集口径:cgroup = 本容器(cgroup v2);host = /proc 整机;none = 取不到 */
|
||
export const ResourceScope = z.enum(["cgroup", "host", "none"]);
|
||
export type ResourceScope = z.infer<typeof ResourceScope>;
|
||
|
||
const Num = z.number().nonnegative().nullable();
|
||
|
||
export const ResourceSample = z.object({
|
||
at: Timestamp,
|
||
/** CPU 占用 %(相对可用核数,0–100) */
|
||
cpuPercent: Num,
|
||
memoryUsedBytes: Num,
|
||
memoryPercent: Num,
|
||
netRxBps: Num,
|
||
netTxBps: Num,
|
||
diskReadBps: Num,
|
||
diskWriteBps: Num,
|
||
});
|
||
export type ResourceSample = z.infer<typeof ResourceSample>;
|
||
|
||
export const SystemResources = z.object({
|
||
at: Timestamp,
|
||
/** 采样间隔(秒) */
|
||
intervalSec: z.number().positive(),
|
||
/** 返回的趋势每点代表的秒数(长时间窗口按桶取平均) */
|
||
bucketSec: z.number().positive(),
|
||
cpu: z.object({
|
||
scope: ResourceScope,
|
||
percent: Num,
|
||
/** 可用核数:cgroup cpu.max 的限额,否则为在线核数 */
|
||
cores: Num,
|
||
/** 整机 CPU 占用 %(/proc/stat),与 scope 无关 */
|
||
hostPercent: Num,
|
||
/** 整机 1 / 5 / 15 分钟平均负载(3 个数) */
|
||
load: z.array(z.number()).nullable(),
|
||
}),
|
||
memory: z.object({
|
||
scope: ResourceScope,
|
||
/** 已用:cgroup 为 memory.current − inactive_file(同 docker stats);整机为 MemTotal − MemAvailable */
|
||
usedBytes: Num,
|
||
/** 上限:cgroup memory.max(不限时退回整机总量) */
|
||
limitBytes: Num,
|
||
percent: Num,
|
||
hostTotalBytes: Num,
|
||
hostAvailableBytes: Num,
|
||
swapUsedBytes: Num,
|
||
}),
|
||
network: z.object({
|
||
scope: ResourceScope,
|
||
rxBps: Num,
|
||
txBps: Num,
|
||
rxTotalBytes: Num,
|
||
txTotalBytes: Num,
|
||
}),
|
||
diskIo: z.object({ scope: ResourceScope, readBps: Num, writeBps: Num }),
|
||
/** 整机已运行秒数(/proc/uptime) */
|
||
hostUptimeSec: Num,
|
||
samples: z.array(ResourceSample),
|
||
});
|
||
export type SystemResources = z.infer<typeof SystemResources>;
|
||
|
||
export const SystemResourcesQuery = z.object({
|
||
/** 趋势窗口(分钟),5–360,缺省 60 */
|
||
minutes: z.coerce.number().int().min(5).max(360).default(60),
|
||
});
|
||
export type SystemResourcesQuery = z.infer<typeof SystemResourcesQuery>;
|