Skip to content

Commit 8de4a32

Browse files
committed
feat(guest): add cpu_iowait_ratio to Metrics RPC
1 parent 225449f commit 8de4a32

5 files changed

Lines changed: 61 additions & 26 deletions

File tree

internal/guest/metrics_linux.go

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,12 @@ import (
1212
"time"
1313
)
1414

15-
// cpuUsage samples /proc/stat twice 100ms apart and returns the ratio 0.0–1.0.
16-
func cpuUsage() (float64, error) {
17-
s1, err := readCPUStat()
18-
if err != nil {
19-
return 0, err
20-
}
21-
time.Sleep(100 * time.Millisecond)
22-
s2, err := readCPUStat()
23-
if err != nil {
24-
return 0, err
25-
}
26-
total := float64(s2.total - s1.total)
27-
idle := float64(s2.idle - s1.idle)
28-
if total == 0 {
29-
return 0, nil
30-
}
31-
return (total - idle) / total, nil
15+
type cpuStat struct {
16+
total uint64
17+
idle uint64
18+
iowait uint64
3219
}
3320

34-
type cpuStat struct{ total, idle uint64 }
35-
3621
func readCPUStat() (cpuStat, error) {
3722
f, err := os.Open("/proc/stat")
3823
if err != nil {
@@ -59,11 +44,38 @@ func readCPUStat() (cpuStat, error) {
5944
if len(vals) > 3 {
6045
idle = vals[3]
6146
}
62-
return cpuStat{total: total, idle: idle}, nil
47+
iowait := uint64(0)
48+
if len(vals) > 4 {
49+
iowait = vals[4]
50+
}
51+
return cpuStat{total: total, idle: idle, iowait: iowait}, nil
6352
}
6453
return cpuStat{}, fmt.Errorf("cpu line not found in /proc/stat")
6554
}
6655

56+
// cpuAndIOWaitUsage samples /proc/stat twice 100ms apart and returns both
57+
// the CPU usage ratio and the iowait ratio (both 0.0–1.0).
58+
func cpuAndIOWaitUsage() (cpuRatio, iowaitRatio float64, err error) {
59+
s1, err := readCPUStat()
60+
if err != nil {
61+
return
62+
}
63+
time.Sleep(100 * time.Millisecond)
64+
s2, err := readCPUStat()
65+
if err != nil {
66+
return
67+
}
68+
total := float64(s2.total - s1.total)
69+
if total == 0 {
70+
return
71+
}
72+
idle := float64(s2.idle - s1.idle)
73+
iowait := float64(s2.iowait - s1.iowait)
74+
cpuRatio = (total - idle) / total
75+
iowaitRatio = iowait / total
76+
return
77+
}
78+
6779
// memUsedBytes returns MemTotal - MemAvailable from /proc/meminfo.
6880
func memUsedBytes() (int64, error) {
6981
f, err := os.Open("/proc/meminfo")

internal/guest/server.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ func (s *Server) HTTPCheck(_ context.Context, req *pb.HTTPCheckRequest) (*pb.HTT
8484

8585
// Metrics reads CPU, memory and disk usage from /proc and syscall.
8686
func (s *Server) Metrics(_ context.Context, _ *pb.MetricsRequest) (*pb.MetricsResponse, error) {
87-
cpu, err := cpuUsage()
87+
cpu, iowait, err := cpuAndIOWaitUsage()
8888
if err != nil {
8989
cpu = 0
90+
iowait = 0
9091
}
9192
mem, err := memUsedBytes()
9293
if err != nil {
@@ -98,6 +99,7 @@ func (s *Server) Metrics(_ context.Context, _ *pb.MetricsRequest) (*pb.MetricsRe
9899
}
99100
return &pb.MetricsResponse{
100101
CpuUsageRatio: cpu,
102+
CpuIowaitRatio: iowait,
101103
MemoryUsedBytes: mem,
102104
DiskUsedBytes: disk,
103105
}, nil

internal/guest/server_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,17 @@ func TestMetrics_returns(t *testing.T) {
121121
}
122122
}
123123

124+
func TestMetrics_iowait(t *testing.T) {
125+
client := startTestServer(t)
126+
resp, err := client.Metrics(context.Background(), &pb.MetricsRequest{})
127+
if err != nil {
128+
t.Fatal(err)
129+
}
130+
if resp.CpuIowaitRatio < 0 || resp.CpuIowaitRatio > 1 {
131+
t.Errorf("cpu_iowait_ratio = %f, want 0.0–1.0", resp.CpuIowaitRatio)
132+
}
133+
}
134+
124135
func TestHTTPCheck_connectionRefused(t *testing.T) {
125136
// Use a port we know has no listener (bind then close to get a free port)
126137
l, err := net.Listen("tcp", "127.0.0.1:0")

internal/proto/guest/guest.pb.go

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/proto/guest/guest.proto

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ message HTTPCheckResponse {
3535
message MetricsRequest {}
3636

3737
message MetricsResponse {
38-
double cpu_usage_ratio = 1;
39-
int64 memory_used_bytes = 2;
40-
int64 disk_used_bytes = 3;
38+
double cpu_usage_ratio = 1;
39+
int64 memory_used_bytes = 2;
40+
int64 disk_used_bytes = 3;
41+
double cpu_iowait_ratio = 4;
4142
}

0 commit comments

Comments
 (0)