ed063ab1fe
Capture desktop-specific system, session, Noctalia, and Pi integration alongside shared laptop support. Retire obsolete X11 configuration and make package ownership explicit for repeatable Decman deployments.
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
|