Files
tia-love/internal/docker/stats.go
T

97 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package docker
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/docker/docker/api/types/container"
)
// Stats — snapshot metrik kontainer (kumulatif untuk net/disk; app menghitung
// laju dari selisih antar snapshot).
type Stats struct {
CPUPercent float64
MemUsed uint64 // usage − cache (seperti `docker stats`)
MemLimit uint64
MemPercent float64
NetRx uint64 // kumulatif
NetTx uint64 // kumulatif
BlkRead uint64 // kumulatif
BlkWrite uint64 // kumulatif
PIDs int
At time.Time
}
// StatsOnce mengambil satu snapshot statistik (one-shot, tanpa stream).
func (c *Client) StatsOnce(ctx context.Context, id string) (Stats, error) {
resp, err := c.cli.ContainerStatsOneShot(ctx, id)
if err != nil {
return Stats{}, fmt.Errorf("docker: stats: %w", err)
}
defer resp.Body.Close()
var raw container.StatsResponse
if err := json.NewDecoder(resp.Body).Decode(&raw); err != nil {
return Stats{}, fmt.Errorf("docker: decode stats: %w", err)
}
return computeStats(&raw), nil
}
// computeStats — rumus yang sama dengan `docker stats` (CPU dari delta
// pre/cpu-stats, memori usage − cache), dipisah agar bisa diuji tanpa daemon.
func computeStats(s *container.StatsResponse) Stats {
// CPU% = (Δcpu / Δsystem) × onlineCPU × 100
cpuDelta := float64(s.CPUStats.CPUUsage.TotalUsage) - float64(s.PreCPUStats.CPUUsage.TotalUsage)
sysDelta := float64(s.CPUStats.SystemUsage) - float64(s.PreCPUStats.SystemUsage)
online := s.CPUStats.OnlineCPUs
if online == 0 {
online = uint32(len(s.CPUStats.CPUUsage.PercpuUsage))
}
cpuPct := 0.0
if sysDelta > 0 && cpuDelta > 0 {
cpuPct = cpuDelta / sysDelta * float64(online) * 100
}
memUsed := s.MemoryStats.Usage
if cache, ok := s.MemoryStats.Stats["cache"]; ok && cache < memUsed {
memUsed -= cache
}
memPct := 0.0
if s.MemoryStats.Limit > 0 {
memPct = float64(memUsed) / float64(s.MemoryStats.Limit) * 100
}
// Net: jumlahkan semua interface (kumulatif).
var rx, tx uint64
for _, n := range s.Networks {
rx += n.RxBytes
tx += n.TxBytes
}
// Blok I/O: jumlahkan per operasi (kumulatif).
var rd, wr uint64
for _, b := range s.BlkioStats.IoServiceBytesRecursive {
switch b.Op {
case "Read", "read":
rd += b.Value
case "Write", "write":
wr += b.Value
}
}
return Stats{
CPUPercent: cpuPct,
MemUsed: memUsed,
MemLimit: s.MemoryStats.Limit,
MemPercent: memPct,
NetRx: rx,
NetTx: tx,
BlkRead: rd,
BlkWrite: wr,
PIDs: int(s.PidsStats.Current),
At: time.Now(),
}
}