feat: add Prometheus metrics parser for llama-swap GPU series

This commit is contained in:
2026-08-14 10:39:26 -06:00
parent fa46857ccb
commit c4082baebc
3 changed files with 127 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
export interface PromSample {
metric: string;
labels: Record<string, string>;
value: number;
}
const LINE_RE = /^([A-Za-z_:][A-Za-z0-9_:]*)(?:\{([^}]*)\})?\s+(-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)$/;
export function parsePrometheus(text: string): PromSample[] {
const samples: PromSample[] = [];
for (const rawLine of text.split("\n")) {
const line = rawLine.trim();
if (!line || line.startsWith("#")) continue;
const m = LINE_RE.exec(line);
if (!m) continue;
const labels: Record<string, string> = {};
if (m[2]) {
for (const pair of m[2].split(",")) {
const eq = pair.indexOf("=");
if (eq === -1) continue;
const value = pair.slice(eq + 1).trim();
labels[pair.slice(0, eq).trim()] = value.replace(/^"(.*)"$/, "$1");
}
}
samples.push({ metric: m[1], labels, value: parseFloat(m[3]) });
}
return samples;
}
export type GpuMetricKind = "util_percent" | "memory_util_percent" | "temperature" | "power" | "fan";
export const GPU_SERIES: Record<string, GpuMetricKind> = {
llamaswap_gpu_util_percent: "util_percent",
llamaswap_gpu_memory_util_percent: "memory_util_percent",
llamaswap_gpu_temperature_celsius: "temperature",
llamaswap_gpu_power_draw_watts: "power",
llamaswap_gpu_fan_speed_percent: "fan",
};
export interface GpuSample {
id: string;
name: string;
kind: GpuMetricKind;
value: number;
}
export function parseGpuMetrics(text: string): GpuSample[] {
const out: GpuSample[] = [];
for (const s of parsePrometheus(text)) {
const kind = GPU_SERIES[s.metric];
if (!kind) continue;
const id = s.labels["id"];
if (id === undefined) continue;
out.push({ id, name: s.labels["name"] ?? "", kind, value: s.value });
}
return out;
}
export function gpuInfos(samples: GpuSample[]): { id: string; name: string }[] {
const byId = new Map<string, string>();
for (const s of samples) {
if (!byId.has(s.id)) byId.set(s.id, s.name);
}
return [...byId.entries()]
.sort((a, b) => parseInt(a[0], 10) - parseInt(b[0], 10))
.map(([id, name]) => ({ id, name }));
}