Skip to content

Commit

Permalink
Merge pull request #947 from mackerelio/iowait-can-be-reset
Browse files Browse the repository at this point in the history
Avoid iowait percentage's overflow when counter is reset
  • Loading branch information
Arthur1 committed Nov 17, 2023
2 parents 952c001 + 788d2ad commit e6ac1b6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
3 changes: 2 additions & 1 deletion metrics/linux/cpuusage.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/mackerelio/go-osstat/cpu"
"github.com/mackerelio/golib/logging"
"github.com/mackerelio/mackerel-agent/metrics"
"github.com/mackerelio/mackerel-agent/util"
)

/*
Expand Down Expand Up @@ -55,7 +56,7 @@ func (g *CPUUsageGenerator) Generate() (metrics.Values, error) {
"cpu.idle.percentage": float64(current.Idle-previous.Idle) * cpuCount * 100.0 / totalDiff,
}
if current.StatCount >= 5 {
ret["cpu.iowait.percentage"] = float64(current.Iowait-previous.Iowait) * cpuCount * 100.0 / totalDiff
ret["cpu.iowait.percentage"] = float64(util.DiffResettableCounter(current.Iowait, previous.Iowait)) * cpuCount * 100.0 / totalDiff
}
if current.StatCount >= 6 {
ret["cpu.irq.percentage"] = float64(current.Irq-previous.Irq) * cpuCount * 100.0 / totalDiff
Expand Down
11 changes: 11 additions & 0 deletions util/calc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package util

// Calculate incremental difference of uint64 counters that can be reset.
// Avoiding overflow, return current value if it is smaller than previous one.
func DiffResettableCounter(current, previous uint64) uint64 {
if current < previous {
// counter has been reset
return current
}
return current - previous
}
25 changes: 25 additions & 0 deletions util/calc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package util

import (
"fmt"
"testing"
)

func TestDiffResettableCounter(t *testing.T) {
cases := []struct {
inCurrent uint64
inPrevious uint64
want uint64
}{
{100, 30, 70},
{20, 50, 20}, // counter has been reset
}
for _, tt := range cases {
t.Run(fmt.Sprintf("%d - %d", tt.inCurrent, tt.inPrevious), func(t *testing.T) {
got := DiffResettableCounter(tt.inCurrent, tt.inPrevious)
if got != tt.want {
t.Errorf("want=%d, got=%d", tt.want, got)
}
})
}
}

0 comments on commit e6ac1b6

Please sign in to comment.