88 lines
2.4 KiB
Lua
88 lines
2.4 KiB
Lua
-- Sum each logical CPU's interval utilization. Unlike the built-in average,
|
|
-- this follows Unix tools by allowing the value to exceed 100%.
|
|
local command = [[awk '
|
|
/^cpu[0-9]+ / {
|
|
total = 0
|
|
for (i = 2; i <= NF; i++) total += $i
|
|
idle = $5 + $6
|
|
printf "%s %.0f %.0f\n", $1, total, idle
|
|
}' /proc/stat]]
|
|
|
|
local previous = {}
|
|
local request_in_flight = false
|
|
|
|
local function colorForUsage(percent)
|
|
if percent >= 85 then
|
|
return "#ff453a" -- red
|
|
end
|
|
if percent >= 70 then
|
|
return "#ff8800" -- orange
|
|
end
|
|
if percent >= 50 then
|
|
return "#ffd60a" -- yellow
|
|
end
|
|
return "#ffffff" -- white
|
|
end
|
|
|
|
local function renderStatus(text, color)
|
|
barWidget.render(ui.row({ gap = 4, align = "center" }, {
|
|
ui.glyph({ name = "cpu", size = 14, color = color }),
|
|
ui.label({ text = text, color = color }),
|
|
}))
|
|
end
|
|
|
|
function update()
|
|
noctalia.setUpdateInterval(2000)
|
|
|
|
if request_in_flight then
|
|
return
|
|
end
|
|
|
|
request_in_flight = true
|
|
noctalia.runAsync(command, function(result)
|
|
request_in_flight = false
|
|
|
|
if result.exitCode ~= 0 then
|
|
renderStatus("CPU —", "#fff1e6")
|
|
barWidget.setTooltip("Unable to read CPU utilization")
|
|
return
|
|
end
|
|
|
|
local utilization = 0
|
|
local sampled = 0
|
|
for line in string.gmatch(result.stdout, "[^\r\n]+") do
|
|
local name, total, idle = string.match(line, "^(cpu%d+) (%d+) (%d+)$")
|
|
total = tonumber(total)
|
|
idle = tonumber(idle)
|
|
local prior = previous[name]
|
|
|
|
if prior ~= nil then
|
|
local total_delta = total - prior.total
|
|
local idle_delta = idle - prior.idle
|
|
if total_delta > 0 then
|
|
utilization = utilization + (100 * (total_delta - idle_delta) / total_delta)
|
|
sampled = sampled + 1
|
|
end
|
|
end
|
|
|
|
previous[name] = { total = total, idle = idle }
|
|
end
|
|
|
|
if sampled > 0 then
|
|
-- Keep the aggregate display, but base its heat color on average
|
|
-- utilization per logical CPU so multicore systems do not stay red.
|
|
local per_cpu_utilization = utilization / sampled
|
|
renderStatus(string.format("%.0f%%", utilization), colorForUsage(per_cpu_utilization))
|
|
barWidget.setTooltip(
|
|
string.format(
|
|
"Aggregate CPU utilization (100%% per logical CPU) · %.0f%% average per CPU",
|
|
per_cpu_utilization
|
|
)
|
|
)
|
|
else
|
|
renderStatus("—", "#fff1e6")
|
|
barWidget.setTooltip("Sampling CPU utilization…")
|
|
end
|
|
end)
|
|
end
|