mirror of
https://github.com/henrygd/beszel.git
synced 2026-08-19 08:47:46 +02:00
feat: track battery levels per device
This commit is contained in:
@@ -186,6 +186,9 @@ func AverageSystemStatsSlice(records []system.Stats) system.Stats {
|
||||
|
||||
// necessary because uint8 is not big enough for the sum
|
||||
batterySum := 0
|
||||
batteryCount := 0
|
||||
batterySums := make(map[string]uint64)
|
||||
batteryCounts := make(map[string]uint64)
|
||||
// accumulate per-core usage across records
|
||||
var cpuCoresSums []uint64
|
||||
// accumulate cpu breakdown [user, system, iowait, steal, idle]
|
||||
@@ -232,8 +235,15 @@ func AverageSystemStatsSlice(records []system.Stats) system.Stats {
|
||||
for i := range stats.DiskIoStats {
|
||||
sum.DiskIoStats[i] += stats.DiskIoStats[i]
|
||||
}
|
||||
batterySum += int(stats.Battery[0])
|
||||
sum.Battery[1] = stats.Battery[1]
|
||||
if hasBattery(stats.Battery, stats.Batteries) {
|
||||
batterySum += int(stats.Battery[0])
|
||||
batteryCount++
|
||||
sum.Battery[1] = stats.Battery[1]
|
||||
}
|
||||
for name, percent := range stats.Batteries {
|
||||
batterySums[name] += uint64(percent)
|
||||
batteryCounts[name]++
|
||||
}
|
||||
|
||||
// accumulate per-core usage if present
|
||||
if stats.CpuCoresUsage != nil {
|
||||
@@ -379,7 +389,15 @@ func AverageSystemStatsSlice(records []system.Stats) system.Stats {
|
||||
sum.LoadAvg[2] = twoDecimals(sum.LoadAvg[2] / count)
|
||||
sum.Bandwidth[0] = sum.Bandwidth[0] / uint64(count)
|
||||
sum.Bandwidth[1] = sum.Bandwidth[1] / uint64(count)
|
||||
sum.Battery[0] = uint8(batterySum / int(count))
|
||||
if batteryCount > 0 {
|
||||
sum.Battery[0] = uint8(batterySum / batteryCount)
|
||||
}
|
||||
if len(batterySums) > 0 {
|
||||
sum.Batteries = make(map[string]uint8, len(batterySums))
|
||||
for name, total := range batterySums {
|
||||
sum.Batteries[name] = uint8(total / batteryCounts[name])
|
||||
}
|
||||
}
|
||||
|
||||
// Average network interfaces
|
||||
if sum.NetworkInterfaces != nil {
|
||||
@@ -467,6 +485,10 @@ func AverageSystemStatsSlice(records []system.Stats) system.Stats {
|
||||
return sum
|
||||
}
|
||||
|
||||
func hasBattery(legacy [2]uint8, batteries map[string]uint8) bool {
|
||||
return legacy != [2]uint8{} || len(batteries) > 0
|
||||
}
|
||||
|
||||
// Calculate the average stats of a list of container_stats records
|
||||
func (rm *RecordManager) AverageContainerStats(db dbx.Builder, records RecordIds) []container.Stats {
|
||||
allStats := make([][]container.Stats, 0, len(records))
|
||||
|
||||
@@ -602,6 +602,28 @@ func TestAverageSystemStatsSlice_BatteryLastChargeState(t *testing.T) {
|
||||
assert.Equal(t, uint8(0), result.Battery[1]) // last record's charge state
|
||||
}
|
||||
|
||||
func TestAverageSystemStatsSlice_BatteriesIndependentSamples(t *testing.T) {
|
||||
input := []system.Stats{
|
||||
{Battery: [2]uint8{80, 4}, Batteries: map[string]uint8{"Primary": 80, "Mouse": 0}},
|
||||
{Battery: [2]uint8{60, 3}, Batteries: map[string]uint8{"Primary": 60}},
|
||||
{Battery: [2]uint8{30, 4}, Batteries: map[string]uint8{"Mouse": 40}},
|
||||
{},
|
||||
}
|
||||
result := records.AverageSystemStatsSlice(input)
|
||||
assert.Equal(t, map[string]uint8{"Primary": 70, "Mouse": 20}, result.Batteries)
|
||||
assert.Equal(t, uint8(56), result.Battery[0], "representative battery excludes absent samples")
|
||||
assert.Equal(t, uint8(4), result.Battery[1], "representative state comes from its latest sample")
|
||||
}
|
||||
|
||||
func TestAverageSystemStatsSlice_ZeroRepresentativeBattery(t *testing.T) {
|
||||
result := records.AverageSystemStatsSlice([]system.Stats{
|
||||
{Battery: [2]uint8{0, 1}, Batteries: map[string]uint8{"Primary": 0}},
|
||||
{},
|
||||
})
|
||||
assert.Equal(t, [2]uint8{0, 1}, result.Battery)
|
||||
assert.Equal(t, map[string]uint8{"Primary": 0}, result.Batteries)
|
||||
}
|
||||
|
||||
func TestAverageSystemStatsSlice_ThreeRecordsRounding(t *testing.T) {
|
||||
input := []system.Stats{
|
||||
{Cpu: 10.0, Mem: 8.0},
|
||||
|
||||
Reference in New Issue
Block a user