add docker container net stats

This commit is contained in:
Henry Dollman
2024-08-04 13:26:17 -04:00
parent c3e3d483b0
commit 2a3b228668
11 changed files with 276 additions and 67 deletions

View File

@@ -26,8 +26,8 @@ import (
var Version = "0.1.1"
var containerCpuMap = make(map[string][2]uint64)
var containerCpuMutex = &sync.Mutex{}
var containerStatsMap = make(map[string]*PrevContainerStats)
var containerStatsMutex = &sync.Mutex{}
var sem = make(chan struct{}, 15)
@@ -53,7 +53,7 @@ var netIoStats = NetIoStats{
Name: "",
}
// dockerClient for docker engine api
// client for docker engine api
var dockerClient = newDockerClient()
func getSystemStats() (*SystemInfo, *SystemStats) {
@@ -175,7 +175,7 @@ func getDockerStats() ([]*ContainerStats, error) {
// note: can't use Created field because it's not updated on restart
if strings.HasSuffix(ctr.Status, "seconds") {
// if so, remove old container data
delete(containerCpuMap, ctr.IdShort)
delete(containerStatsMap, ctr.IdShort)
}
wg.Add(1)
go func() {
@@ -183,7 +183,7 @@ func getDockerStats() ([]*ContainerStats, error) {
cstats, err := getContainerStats(ctr)
if err != nil {
// delete container from map and retry once
delete(containerCpuMap, ctr.IdShort)
delete(containerStatsMap, ctr.IdShort)
cstats, err = getContainerStats(ctr)
if err != nil {
log.Printf("Error getting container stats: %+v\n", err)
@@ -196,10 +196,10 @@ func getDockerStats() ([]*ContainerStats, error) {
wg.Wait()
for id := range containerCpuMap {
for id := range containerStatsMap {
if _, exists := validIds[id]; !exists {
// log.Printf("Removing container cpu map entry: %+v\n", id)
delete(containerCpuMap, id)
delete(containerStatsMap, id)
}
}
@@ -229,27 +229,45 @@ func getContainerStats(ctr *Container) (*ContainerStats, error) {
memCache = statsJson.MemoryStats.Stats["cache"]
}
usedMemory := statsJson.MemoryStats.Usage - memCache
// pctMemory := float64(usedMemory) / float64(statsJson.MemoryStats.Limit) * 100
containerStatsMutex.Lock()
defer containerStatsMutex.Unlock()
// add empty values if they doesn't exist in map
_, initialized := containerStatsMap[ctr.IdShort]
if !initialized {
containerStatsMap[ctr.IdShort] = &PrevContainerStats{}
}
// cpu
// add default values to containerCpu if it doesn't exist
containerCpuMutex.Lock()
defer containerCpuMutex.Unlock()
if _, ok := containerCpuMap[ctr.IdShort]; !ok {
containerCpuMap[ctr.IdShort] = [2]uint64{0, 0}
}
cpuDelta := statsJson.CPUStats.CPUUsage.TotalUsage - containerCpuMap[ctr.IdShort][0]
systemDelta := statsJson.CPUStats.SystemUsage - containerCpuMap[ctr.IdShort][1]
cpuDelta := statsJson.CPUStats.CPUUsage.TotalUsage - containerStatsMap[ctr.IdShort].Cpu[0]
systemDelta := statsJson.CPUStats.SystemUsage - containerStatsMap[ctr.IdShort].Cpu[1]
cpuPct := float64(cpuDelta) / float64(systemDelta) * 100
if cpuPct > 100 {
return &ContainerStats{}, fmt.Errorf("%s cpu pct greater than 100: %+v", name, cpuPct)
}
containerCpuMap[ctr.IdShort] = [2]uint64{statsJson.CPUStats.CPUUsage.TotalUsage, statsJson.CPUStats.SystemUsage}
containerStatsMap[ctr.IdShort].Cpu = [2]uint64{statsJson.CPUStats.CPUUsage.TotalUsage, statsJson.CPUStats.SystemUsage}
// network
var total_sent, total_recv, sent_delta, recv_delta uint64
for _, v := range statsJson.Networks {
total_sent += v.TxBytes
total_recv += v.RxBytes
}
// prevent first run from sending all prev sent/recv bytes
if initialized {
sent_delta = total_sent - containerStatsMap[ctr.IdShort].Net[0]
recv_delta = total_recv - containerStatsMap[ctr.IdShort].Net[1]
// log.Printf("sent delta: %+v, recv delta: %+v\n", sent_delta, recv_delta)
}
containerStatsMap[ctr.IdShort].Net = [2]uint64{total_sent, total_recv}
cStats := &ContainerStats{
Name: name,
Cpu: twoDecimals(cpuPct),
Mem: bytesToMegabytes(float64(usedMemory)),
Name: name,
Cpu: twoDecimals(cpuPct),
Mem: bytesToMegabytes(float64(usedMemory)),
NetworkSent: bytesToMegabytes(float64(sent_delta)),
NetworkRecv: bytesToMegabytes(float64(recv_delta)),
// MemPct: twoDecimals(pctMemory),
}
return cStats, nil
@@ -429,10 +447,8 @@ func newDockerClient() *http.Client {
log.Fatal("Unsupported DOCKER_HOST: " + parsedURL.Scheme)
}
client := &http.Client{
return &http.Client{
Timeout: time.Second,
Transport: transport,
}
return client
}

View File

@@ -35,10 +35,11 @@ type SystemStats struct {
}
type ContainerStats struct {
Name string `json:"n"`
Cpu float64 `json:"c"`
Mem float64 `json:"m"`
// MemPct float64 `json:"mp"`
Name string `json:"n"`
Cpu float64 `json:"c"`
Mem float64 `json:"m"`
NetworkSent float64 `json:"ns"`
NetworkRecv float64 `json:"nr"`
}
type Container struct {
@@ -65,20 +66,22 @@ type Container struct {
type CStats struct {
// Common stats
Read time.Time `json:"read"`
PreRead time.Time `json:"preread"`
// Read time.Time `json:"read"`
// PreRead time.Time `json:"preread"`
// Linux specific stats, not populated on Windows.
// PidsStats PidsStats `json:"pids_stats,omitempty"`
// BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
// Windows specific stats, not populated on Linux.
NumProcs uint32 `json:"num_procs"`
// NumProcs uint32 `json:"num_procs"`
// StorageStats StorageStats `json:"storage_stats,omitempty"`
// Networks request version >=1.21
Networks map[string]NetworkStats
// Shared stats
CPUStats CPUStats `json:"cpu_stats,omitempty"`
PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous"
CPUStats CPUStats `json:"cpu_stats,omitempty"`
// PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous"
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
}
@@ -90,7 +93,7 @@ type CPUStats struct {
SystemUsage uint64 `json:"system_cpu_usage,omitempty"`
// Online CPUs. Linux only.
OnlineCPUs uint32 `json:"online_cpus,omitempty"`
// OnlineCPUs uint32 `json:"online_cpus,omitempty"`
// Throttling Data. Linux only.
// ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
@@ -104,19 +107,19 @@ type CPUUsage struct {
// Total CPU time consumed per core (Linux). Not used on Windows.
// Units: nanoseconds.
PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
// PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
// Time spent by tasks of the cgroup in kernel mode (Linux).
// Time spent by all container processes in kernel mode (Windows).
// Units: nanoseconds (Linux).
// Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers.
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
// UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
// Time spent by tasks of the cgroup in user mode (Linux).
// Time spent by all container processes in user mode (Windows).
// Units: nanoseconds (Linux).
// Units: 100's of nanoseconds (Windows). Not populated for Hyper-V Containers
UsageInUsermode uint64 `json:"usage_in_usermode"`
// UsageInUsermode uint64 `json:"usage_in_usermode"`
}
type MemoryStats struct {
@@ -125,20 +128,27 @@ type MemoryStats struct {
Usage uint64 `json:"usage,omitempty"`
Cache uint64 `json:"cache,omitempty"`
// maximum usage ever recorded.
MaxUsage uint64 `json:"max_usage,omitempty"`
// MaxUsage uint64 `json:"max_usage,omitempty"`
// TODO(vishh): Export these as stronger types.
// all the stats exported via memory.stat.
Stats map[string]uint64 `json:"stats,omitempty"`
// number of times memory usage hits limits.
Failcnt uint64 `json:"failcnt,omitempty"`
Limit uint64 `json:"limit,omitempty"`
// Failcnt uint64 `json:"failcnt,omitempty"`
// Limit uint64 `json:"limit,omitempty"`
// committed bytes
Commit uint64 `json:"commitbytes,omitempty"`
// peak committed bytes
CommitPeak uint64 `json:"commitpeakbytes,omitempty"`
// private working set
PrivateWorkingSet uint64 `json:"privateworkingset,omitempty"`
// // committed bytes
// Commit uint64 `json:"commitbytes,omitempty"`
// // peak committed bytes
// CommitPeak uint64 `json:"commitpeakbytes,omitempty"`
// // private working set
// PrivateWorkingSet uint64 `json:"privateworkingset,omitempty"`
}
type NetworkStats struct {
// Bytes received. Windows and Linux.
RxBytes uint64 `json:"rx_bytes"`
// Bytes sent. Windows and Linux.
TxBytes uint64 `json:"tx_bytes"`
}
type DiskIoStats struct {
@@ -154,3 +164,8 @@ type NetIoStats struct {
Time time.Time
Name string
}
type PrevContainerStats struct {
Cpu [2]uint64
Net [2]uint64
}