优化CPU绘图
This commit is contained in:
@@ -1340,7 +1340,6 @@
|
|||||||
const cpuValueHtml = `
|
const cpuValueHtml = `
|
||||||
<div style="display: flex; align-items: baseline; gap: 8px;">
|
<div style="display: flex; align-items: baseline; gap: 8px;">
|
||||||
<span style="font-weight: 700; font-size: 1.1rem;">${formatPercent(data.cpuBusy)}</span>
|
<span style="font-weight: 700; font-size: 1.1rem;">${formatPercent(data.cpuBusy)}</span>
|
||||||
<span style="font-size: 0.7rem; color: var(--text-secondary); font-weight: normal;">(IO Wait: ${data.cpuIowait.toFixed(1)}%, Busy Others: ${data.cpuOther.toFixed(1)}%)</span>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
// Define metrics to show
|
// Define metrics to show
|
||||||
|
|||||||
@@ -549,14 +549,6 @@ async function getServerDetails(baseUrl, instance, job) {
|
|||||||
|
|
||||||
// Queries based on the requested dashboard structure
|
// Queries based on the requested dashboard structure
|
||||||
const queries = {
|
const queries = {
|
||||||
// Split CPU
|
|
||||||
cpuSystem: `avg(rate(node_cpu_seconds_total{mode="system", instance="${node}"}[1m])) * 100`,
|
|
||||||
cpuUser: `avg(rate(node_cpu_seconds_total{mode="user", instance="${node}"}[1m])) * 100`,
|
|
||||||
cpuIowait: `avg(rate(node_cpu_seconds_total{mode="iowait", instance="${node}"}[1m])) * 100`,
|
|
||||||
cpuIrq: `avg(rate(node_cpu_seconds_total{mode=~"irq|softirq", instance="${node}"}[1m])) * 100`,
|
|
||||||
cpuOther: `avg(rate(node_cpu_seconds_total{mode=~"nice|steal|guest|guest_nice", instance="${node}"}[1m])) * 100`,
|
|
||||||
cpuIdle: `avg(rate(node_cpu_seconds_total{mode="idle", instance="${node}"}[1m])) * 100`,
|
|
||||||
|
|
||||||
cpuBusy: `100 * (1 - avg(rate(node_cpu_seconds_total{mode="idle", instance="${node}"}[1m])))`,
|
cpuBusy: `100 * (1 - avg(rate(node_cpu_seconds_total{mode="idle", instance="${node}"}[1m])))`,
|
||||||
sysLoad: `node_load1{instance="${node}",job="${job}"} * 100 / count(count(node_cpu_seconds_total{instance="${node}",job="${job}"}) by (cpu))`,
|
sysLoad: `node_load1{instance="${node}",job="${job}"} * 100 / count(count(node_cpu_seconds_total{instance="${node}",job="${job}"}) by (cpu))`,
|
||||||
memUsedPct: `(1 - (node_memory_MemAvailable_bytes{instance="${node}", job="${job}"} / node_memory_MemTotal_bytes{instance="${node}", job="${job}"})) * 100`,
|
memUsedPct: `(1 - (node_memory_MemAvailable_bytes{instance="${node}", job="${job}"} / node_memory_MemTotal_bytes{instance="${node}", job="${job}"})) * 100`,
|
||||||
@@ -636,42 +628,18 @@ async function getServerHistory(baseUrl, instance, job, metric, range = '1h', st
|
|||||||
const url = normalizeUrl(baseUrl);
|
const url = normalizeUrl(baseUrl);
|
||||||
const node = resolveToken(instance);
|
const node = resolveToken(instance);
|
||||||
|
|
||||||
// Custom multi-metric handler for CPU Busy
|
// CPU Busy history: 100 - idle
|
||||||
if (metric === 'cpuBusy') {
|
if (metric === 'cpuBusy') {
|
||||||
const modes = {
|
const expr = `100 * (1 - avg(rate(node_cpu_seconds_total{mode="idle", instance="${node}"}[1m])))`;
|
||||||
system: 'system',
|
|
||||||
user: 'user',
|
|
||||||
iowait: 'iowait',
|
|
||||||
irq: 'irq|softirq',
|
|
||||||
other: 'nice|steal|guest|guest_nice',
|
|
||||||
idle: 'idle'
|
|
||||||
};
|
|
||||||
|
|
||||||
const rangeObj = parseRange(range, start, end);
|
const rangeObj = parseRange(range, start, end);
|
||||||
const timestamps = [];
|
const result = await queryRange(url, expr, rangeObj.queryStart, rangeObj.queryEnd, rangeObj.step);
|
||||||
const series = {};
|
|
||||||
Object.keys(modes).forEach(m => series[m] = []);
|
|
||||||
|
|
||||||
const results = await Promise.all(Object.entries(modes).map(async ([name, mode]) => {
|
if (!result || result.length === 0) return { timestamps: [], values: [] };
|
||||||
const expr = `avg(rate(node_cpu_seconds_total{mode=~"${mode}", instance="${node}"}[1m])) * 100`;
|
|
||||||
const res = await queryRange(url, expr, rangeObj.queryStart, rangeObj.queryEnd, rangeObj.step);
|
|
||||||
return { name, values: res.length > 0 ? res[0].values : [] };
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (results[0].values.length === 0) return { timestamps: [], series: {} };
|
return {
|
||||||
|
timestamps: result[0].values.map(v => v[0] * 1000),
|
||||||
// Use first result for timestamps
|
values: result[0].values.map(v => parseFloat(v[1]))
|
||||||
results[0].values.forEach(v => timestamps.push(v[0] * 1000));
|
};
|
||||||
|
|
||||||
results.forEach(r => {
|
|
||||||
r.values.forEach(v => series[r.name].push(parseFloat(v[1])));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pre-calculate busy percentage: 100 - idle
|
|
||||||
const idleValues = series.idle || [];
|
|
||||||
const busyValues = idleValues.map(idleVal => Math.max(0, 100 - idleVal));
|
|
||||||
|
|
||||||
return { timestamps, series, values: busyValues };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map metric keys to Prometheus expressions
|
// Map metric keys to Prometheus expressions
|
||||||
|
|||||||
Reference in New Issue
Block a user