Skip to content

Commit

Permalink
Support cgroup v2
Browse files Browse the repository at this point in the history
  • Loading branch information
MatMaul committed Feb 27, 2021
1 parent 8af63f7 commit ffbd9cf
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 66 deletions.
11 changes: 3 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@ module github.com/groove-x/cgroup-exporter
go 1.11

require (
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/containerd/cgroups v0.0.0-20181001140508-d2400726cfa7
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.3.4-0.20181018102642-03db2b60b820 // indirect
github.com/godbus/dbus v4.1.1-0.20180905195443-5f1bd775722e+incompatible // indirect
github.com/gogo/protobuf v1.2.0 // indirect
github.com/moby/moby v1.13.1
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.0.2-0.20180913141938-5806c3563733 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
)
76 changes: 49 additions & 27 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/containerd/cgroups v0.0.0-20181001140508-d2400726cfa7 h1:HpTs4G3F32Jue3Hu3Tc4hD4d9AhALxYE4+vCO0SkSvw=
github.com/containerd/cgroups v0.0.0-20181001140508-d2400726cfa7/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/cilium/ebpf v0.2.0 h1:Fv93L3KKckEcEHR3oApXVzyBTDA8WAm6VXhPE00N3f8=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68 h1:hkGVFjz+plgr5UfxZUTPFbUFIF/Km6/s+RVRIRHLrrY=
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
Expand All @@ -12,36 +17,53 @@ github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.4-0.20181018102642-03db2b60b820 h1:EQSiSOsNbDAIw+kdd4NPThBl+510eNrB58SRYcKwUK4=
github.com/docker/go-units v0.3.4-0.20181018102642-03db2b60b820/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/godbus/dbus v4.1.1-0.20180905195443-5f1bd775722e+incompatible h1:1EAOqHEDzmRZ+SWNSMZ3nnczBDhMT1jIfE3QZ2iHZ9s=
github.com/godbus/dbus v4.1.1-0.20180905195443-5f1bd775722e+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
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.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/moby/moby v1.13.1 h1:mC5WwQwCXt/dYxZ1cIrRsnJAWw7VdtcTZUIGr4tXzOM=
github.com/moby/moby v1.13.1/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/runtime-spec v1.0.2-0.20180913141938-5806c3563733 h1:M9SVV7xezQ8PC/0NPAek6TUr1IdwVx5wGkdojnXwalM=
github.com/opencontainers/runtime-spec v1.0.2-0.20180913141938-5806c3563733/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
135 changes: 104 additions & 31 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"time"

"github.com/containerd/cgroups"
v1 "github.com/containerd/cgroups/stats/v1"
v2 "github.com/containerd/cgroups/v2"
"github.com/containerd/cgroups/v2/stats"
"github.com/docker/docker/api/types"
"github.com/moby/moby/client"
)
Expand All @@ -41,21 +44,7 @@ func main() {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)

system, err := cgroups.Load(subsystem, cgroups.StaticPath(*cgroupPath))
if err != nil {
log.Fatalf("cgroups load: %s", err)
}

var dockerClient *client.Client
if *enableDocker {
dockerClient, err = client.NewEnvClient()
if err != nil {
log.Fatalf("%v", err)
}
defer dockerClient.Close()
}

http.HandleFunc("/metrics", exportMetrics(system, dockerClient))
http.HandleFunc("/metrics", exportMetrics(*enableDocker))

server := &http.Server{
Addr: *address,
Expand Down Expand Up @@ -113,18 +102,27 @@ func subsystem() ([]cgroups.Subsystem, error) {
return s, nil
}

type cgroupMetrics struct {
*cgroups.Metrics
type cgroupV1Metrics struct {
*v1.Metrics
Process *ProcessStats `json:"process_stats"`
}

func statsCgroups(ctx context.Context, system cgroups.Cgroup) (map[string]*cgroupMetrics, error) {
func statsCgroupsV1(ctx context.Context) (map[string]*cgroupV1Metrics, error) {
// should we support hybrid here ?
if cgroups.Mode() != cgroups.Legacy {
return map[string]*cgroupV1Metrics{}, nil
}
system, err := cgroups.Load(subsystem, cgroups.StaticPath("/system.slice"))
if err != nil {
log.Fatalf("cgroups load: %s", err)
}

processes, err := system.Processes(cgroups.Devices, true)
if err != nil {
return nil, fmt.Errorf("cgroups load: %s", err)
}

groups := make(map[string]*cgroupMetrics, len(processes))
groups := make(map[string]*cgroupV1Metrics, len(processes))
for _, p := range processes {
name := strings.TrimPrefix(p.Path, "/sys/fs/cgroup/devices")
name = strings.TrimSuffix(name, "/")
Expand All @@ -145,25 +143,72 @@ func statsCgroups(ctx context.Context, system cgroups.Cgroup) (map[string]*cgrou
continue
}
ps := processStats(p.Pid)
groups[name] = &cgroupMetrics{
groups[name] = &cgroupV1Metrics{
Metrics: stats,
Process: ps,
}
}
return groups, nil
}

func gatherAllDirs(basepath, path string) []string {
dirs := []string{path}

files, err := ioutil.ReadDir(basepath + "/" + path)

if err != nil {
// TODO
log.Print(err)
}

for _, f := range files {
if f.IsDir() {
dirs = append(dirs, gatherAllDirs(basepath, path+"/"+f.Name())...)
}
}
return dirs
}

func statsCgroupsV2(ctx context.Context) (map[string]*stats.Metrics, error) {
if cgroups.Mode() != cgroups.Unified {
return map[string]*stats.Metrics{}, nil
}
cgroupsMountpoint := "/sys/fs/cgroup"
allCgNames := gatherAllDirs(cgroupsMountpoint, "/system.slice")
allCgNames = append(allCgNames, "/system.slice")

groups := make(map[string]*stats.Metrics, len(allCgNames))

for _, cgName := range allCgNames {
manager, err := v2.LoadManager(cgroupsMountpoint, cgName)
if err != nil {
log.Printf("cgroupsv2 load manager %s: %s", cgName, err)
continue
}
stats, err := manager.Stat()
if err != nil {
log.Printf("cgroupsv2 stat %s: %s", cgName, err)
continue
}
groups[cgName] = stats
}
return groups, nil
}

type dockerStats struct {
CPU types.CPUStats `json:"cpu_stats,omitempty"`
PreCPU types.CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous"
Memory types.MemoryStats `json:"memory_stats,omitempty"`
Process *ProcessStats `json:"process_stats"`
}

func statsDockerContainers(ctx context.Context, dockerClient *client.Client) (map[string]dockerStats, error) {
if dockerClient == nil {
return nil, nil
func statsDockerContainers(ctx context.Context) (map[string]dockerStats, error) {
dockerClient, err := client.NewEnvClient()
if err != nil {
log.Fatalf("%v", err)
}
defer dockerClient.Close()

containers, err := dockerClient.ContainerList(ctx, types.ContainerListOptions{
All: true,
Limit: 0,
Expand Down Expand Up @@ -198,47 +243,75 @@ func statsDockerContainers(ctx context.Context, dockerClient *client.Client) (ma
return dockerContainers, nil
}

func exportMetrics(system cgroups.Cgroup, dockerClient *client.Client) func(w http.ResponseWriter, r *http.Request) {
func exportMetrics(enableDocker bool) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

groups, err := statsCgroups(ctx, system)
groupsV1, err := statsCgroupsV1(ctx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

dockerContainers, err := statsDockerContainers(ctx, dockerClient)
groupsV2, err := statsCgroupsV2(ctx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

var dockerContainers = make(map[string]dockerStats)
if enableDocker {
dockerContainers, err = statsDockerContainers(ctx)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

fmt.Fprintln(w, `# HELP container_cpu_user_seconds_total Cumulative user cpu time consumed in seconds.
# TYPE container_cpu_user_seconds_total counter`)
for name, stats := range groups {
for name, stats := range groupsV1 {
fmt.Fprintf(w, `container_cpu_user_seconds_total{id=%s} %.2f`, strconv.Quote(name), float64(stats.CPU.Usage.User)/1000000000.0)
fmt.Fprintln(w)
}
for name, stats := range groupsV2 {
fmt.Fprintf(w, `container_cpu_user_seconds_total{id=%s} %.2f`, strconv.Quote(name), float64(stats.CPU.UserUsec)/1000000.0)
fmt.Fprintln(w)
}
for name, stats := range dockerContainers {
fmt.Fprintf(w, `container_cpu_user_seconds_total{id=%s} %.2f`, strconv.Quote(name), float64(stats.CPU.CPUUsage.UsageInUsermode)/1000000000.0)
fmt.Fprintln(w)
}

fmt.Fprintln(w, `# HELP container_memory_usage_bytes Current memory usage in bytes, including all memory regardless of when it was accessed
# TYPE container_memory_usage_bytes gauge`)
for name, stats := range groups {
for name, stats := range groupsV1 {
fmt.Fprintf(w, `container_memory_usage_bytes{id=%s} %d`, strconv.Quote(name), stats.Memory.Usage.Usage)
fmt.Fprintln(w)
}
for name, stats := range groupsV2 {
fmt.Fprintf(w, `container_memory_usage_bytes{id=%s} %d`, strconv.Quote(name), stats.Memory.Usage)
fmt.Fprintln(w)
}
for name, stats := range dockerContainers {
fmt.Fprintf(w, `container_memory_usage_bytes{id=%s} %d`, strconv.Quote(name), stats.Memory.Usage)
fmt.Fprintln(w)
}

fmt.Fprintln(w, `# HELP container_memsw_usage_bytes Current memory+swap usage in bytes
# TYPE container_memsw_usage_bytes gauge`)
for name, stats := range groupsV1 {
fmt.Fprintf(w, `container_memsw_usage_bytes{id=%s} %d`, strconv.Quote(name), stats.Memory.Swap.Usage)
fmt.Fprintln(w)
}
for name, stats := range groupsV2 {
fmt.Fprintf(w, `container_memsw_usage_bytes{id=%s} %d`, strconv.Quote(name), stats.Memory.Usage+stats.Memory.SwapUsage)
fmt.Fprintln(w)
}

fmt.Fprintln(w, `# HELP container_memory_rss Size of RSS in bytes.
# TYPE container_memory_rss gauge`)
for name, stats := range groups {
for name, stats := range groupsV1 {
fmt.Fprintf(w, `container_memory_rss{id=%s} %d`, strconv.Quote(name), stats.Memory.RSS)
fmt.Fprintln(w)
}
Expand All @@ -249,7 +322,7 @@ func exportMetrics(system cgroups.Cgroup, dockerClient *client.Client) func(w ht

fmt.Fprintln(w, `# HELP container_open_fds Number of open file descriptors
# TYPE container_open_fds gauge`)
for name, stats := range groups {
for name, stats := range groupsV1 {
if stats.Process == nil {
continue
}
Expand All @@ -266,7 +339,7 @@ func exportMetrics(system cgroups.Cgroup, dockerClient *client.Client) func(w ht

fmt.Fprintln(w, `# HELP container_open_sockets Number of open sockets
# TYPE container_open_sockets gauge`)
for name, stats := range groups {
for name, stats := range groupsV1 {
if stats.Process == nil {
continue
}
Expand Down

0 comments on commit ffbd9cf

Please sign in to comment.