-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update: Implemented source code for tool
- Loading branch information
Showing
4 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Cgroup Stats CLI Tool | ||
This is a tool written in Go that uses the containerd/cgroups library to print out cgroup (control group) statistics for a given cgroup. This package currently only supports cgroupsV1. You can specify the type of stats to print out using command line flags. | ||
|
||
### Why not just use systemd_cgtop? | ||
This tool provides more granular and exact information about the stats it returns as compared to systemd_cgtop (which reports cache memory as part of memory causing misleading information about how much active memory is being used). See: https://systemd-devel.freedesktop.narkive.com/WnOE0u0k/systemd-cgtop-memory-utilization-display-not-useful | ||
|
||
### Dependencies | ||
This tool requires the containerd/cgroups Go library. You can install it using the following command: | ||
```` | ||
go get github.com/containerd/cgroups | ||
```` | ||
|
||
### Usage | ||
You can run the tool using the go run command. You must provide the cgroup path using the -path flag. You can also specify what kind of stats to print out using the -cpu, -mem, -pids, -blkio, and -hugetlb flags. | ||
``` | ||
go run main.go -path=<cgroup_path> [-cpu] [-mem] [-pids] [-blkio] [-hugetlb] | ||
``` | ||
For example, the following command will print out the CPU, Memory, and PIDs stats of the specified cgroup: | ||
|
||
``` | ||
go run main.go -path=/sys/fs/cgroup/unified/system.slice/docker.service -cpu -mem -pids | ||
``` | ||
|
||
### Contributing | ||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module github.com/binsquare/cgroup-stats-cli | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/containerd/cgroups v1.1.0 // indirect | ||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect | ||
github.com/docker/go-units v0.4.0 // indirect | ||
github.com/godbus/dbus/v5 v5.0.4 // indirect | ||
github.com/gogo/protobuf v1.3.2 // indirect | ||
github.com/opencontainers/runtime-spec v1.0.2 // indirect | ||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= | ||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= | ||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= | ||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | ||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= | ||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= | ||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= | ||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= | ||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= | ||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= | ||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||
github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= | ||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= | ||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= | ||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/containerd/cgroups" | ||
v1 "github.com/containerd/cgroups/stats/v1" | ||
) | ||
|
||
type cliOptions struct { | ||
cgroupPath *string | ||
onlyCPU *bool | ||
onlyMem *bool | ||
onlyPids *bool | ||
onlyBlkio *bool | ||
onlyHugetlb *bool | ||
} | ||
|
||
func parseFlags(flags *cliOptions) *cliOptions { | ||
flags.cgroupPath = flag.String("path", "", "The cgroup path to read stats. Path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name") | ||
flags.onlyCPU = flag.Bool("cpu", false, "show cpu stats only") | ||
flags.onlyMem = flag.Bool("mem", false, "show mem stats only") | ||
flags.onlyPids = flag.Bool("pids", false, "show pids stats only") | ||
flags.onlyBlkio = flag.Bool("blkio", false, "show blkio stats only") | ||
flags.onlyHugetlb = flag.Bool("HugeTLB", false, "show hugetlb stats only") | ||
|
||
flag.Parse() | ||
return flags | ||
} | ||
|
||
func getMetrics(cg cgroups.Cgroup) *v1.Metrics { | ||
metrics, err := cg.Stat(cgroups.IgnoreNotExist) | ||
if err != nil { | ||
fmt.Println("err retrieving cgroup stats:", err) | ||
os.Exit(1) | ||
} | ||
|
||
return metrics | ||
} | ||
|
||
func printMetrics(metrics *v1.Metrics, flags *cliOptions) { | ||
if *flags.onlyCPU { | ||
fmt.Printf("CPU Metrics: %+v\n", metrics.CPU) | ||
} | ||
if *flags.onlyMem { | ||
fmt.Printf("Memory Metrics: %+v\n", metrics.Memory) | ||
} | ||
if *flags.onlyPids { | ||
fmt.Printf("PIDs Metrics: %+v\n", metrics.Pids) | ||
} | ||
if *flags.onlyBlkio { | ||
fmt.Printf("BlkIO Metrics: %+v\n", metrics.Blkio) | ||
} | ||
if *flags.onlyHugetlb { | ||
fmt.Printf("HugeTLB Metrics: %+v\n", metrics.Hugetlb) | ||
} | ||
|
||
if !*flags.onlyCPU && !*flags.onlyMem && !*flags.onlyPids && !*flags.onlyBlkio && !*flags.onlyHugetlb { | ||
fmt.Printf("Cgroup metrics: %+v\n", metrics) | ||
} | ||
} | ||
|
||
func main() { | ||
flags := parseFlags(new(cliOptions)) | ||
|
||
if *flags.cgroupPath == "" { | ||
fmt.Println("Missing cgroup path") | ||
os.Exit(1) | ||
} | ||
|
||
cg, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(*flags.cgroupPath)) | ||
if err != nil { | ||
fmt.Println("loading cgroup error:", err) | ||
os.Exit(1) | ||
} | ||
|
||
metrics := getMetrics(cg) | ||
|
||
printMetrics(metrics, flags) | ||
} |