Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get docker container cpu usage from cpuacct.usage #590

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions cpu/cpu_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/shirou/gopsutil/internal/common"
)

var cpu_tick = float64(100)
var CPUTick = float64(100)

func init() {
getconf, err := exec.LookPath("/usr/bin/getconf")
Expand All @@ -25,7 +25,7 @@ func init() {
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
cpu_tick = float64(i)
CPUTick = i
}
}
}
Expand Down Expand Up @@ -251,34 +251,34 @@ func parseStatLine(line string) (*TimesStat, error) {

ct := &TimesStat{
CPU: cpu,
User: float64(user) / cpu_tick,
Nice: float64(nice) / cpu_tick,
System: float64(system) / cpu_tick,
Idle: float64(idle) / cpu_tick,
Iowait: float64(iowait) / cpu_tick,
Irq: float64(irq) / cpu_tick,
Softirq: float64(softirq) / cpu_tick,
User: user / CPUTick,
Nice: nice / CPUTick,
System: system / CPUTick,
Idle: idle / CPUTick,
Iowait: iowait / CPUTick,
Irq: irq / CPUTick,
Softirq: softirq / CPUTick,
}
if len(fields) > 8 { // Linux >= 2.6.11
steal, err := strconv.ParseFloat(fields[8], 64)
if err != nil {
return nil, err
}
ct.Steal = float64(steal) / cpu_tick
ct.Steal = steal / CPUTick
}
if len(fields) > 9 { // Linux >= 2.6.24
guest, err := strconv.ParseFloat(fields[9], 64)
if err != nil {
return nil, err
}
ct.Guest = float64(guest) / cpu_tick
ct.Guest = guest / CPUTick
}
if len(fields) > 10 { // Linux >= 3.2.0
guestNice, err := strconv.ParseFloat(fields[10], 64)
if err != nil {
return nil, err
}
ct.GuestNice = float64(guestNice) / cpu_tick
ct.GuestNice = guestNice / CPUTick
}

return ct, nil
Expand Down
8 changes: 8 additions & 0 deletions docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"

"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
)

Expand All @@ -12,6 +13,13 @@ var ErrCgroupNotAvailable = errors.New("cgroup not available")

var invoke common.Invoker = common.Invoke{}

const nanoseconds = 1e9

type CgroupCPUStat struct {
cpu.TimesStat
Usage float64
}

type CgroupMemStat struct {
ContainerID string `json:"containerID"`
Cache uint64 `json:"cache"`
Expand Down
48 changes: 40 additions & 8 deletions docker/docker_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,19 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
// containerID is same as docker id if you use docker.
// If you use container via systemd.slice, you could use
// containerID = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
func CgroupCPU(containerID string, base string) (*cpu.TimesStat, error) {
func CgroupCPU(containerID string, base string) (*CgroupCPUStat, error) {
return CgroupCPUWithContext(context.Background(), containerID, base)
}

func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*cpu.TimesStat, error) {
// CgroupCPUUsage returnes specified cgroup id CPU usage.
// containerID is same as docker id if you use docker.
// If you use container via systemd.slice, you could use
// containerID = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
func CgroupCPUUsage(containerID string, base string) (float64, error) {
return CgroupCPUUsageWithContext(context.Background(), containerID, base)
}

func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) {
statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat")
lines, err := common.ReadLines(statfile)
if err != nil {
Expand All @@ -103,31 +111,55 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
if len(containerID) == 0 {
containerID = "all"
}
ret := &cpu.TimesStat{CPU: containerID}
ret := &CgroupCPUStat{}
ret.CPU = containerID
for _, line := range lines {
fields := strings.Split(line, " ")
if fields[0] == "user" {
user, err := strconv.ParseFloat(fields[1], 64)
if err == nil {
ret.User = float64(user)
ret.User = user / cpu.CPUTick
}
}
if fields[0] == "system" {
system, err := strconv.ParseFloat(fields[1], 64)
if err == nil {
ret.System = float64(system)
ret.System = system / cpu.CPUTick
}
}
}

usage, err := CgroupCPUUsageWithContext(ctx, containerID, base)
if err != nil {
return nil, err
}
ret.Usage = usage
return ret, nil
}

func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) {
func CgroupCPUUsageWithContext(ctx context.Context, containerID, base string) (float64, error) {
usagefile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.usage")
lines, err := common.ReadLinesOffsetN(usagefile, 0, 1)
if err != nil {
return 0.0, err
}

ns, err := strconv.ParseFloat(lines[0], 64)
if err != nil {
return 0.0, err
}

return ns / nanoseconds, nil
}

func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
return CgroupCPUDockerWithContext(context.Background(), containerid)
}

func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) {
func CgroupCPUDockerUsageWithContext(ctx context.Context, containerid string) (float64, error) {
return CgroupCPUUsage(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
}

func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
}

Expand Down
10 changes: 5 additions & 5 deletions docker/docker_notlinux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package docker

import (
"context"
"github.com/shirou/gopsutil/cpu"

"github.com/shirou/gopsutil/internal/common"
)

Expand Down Expand Up @@ -32,19 +32,19 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
// containerid is same as docker id if you use docker.
// If you use container via systemd.slice, you could use
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/
func CgroupCPU(containerid string, base string) (*cpu.TimesStat, error) {
func CgroupCPU(containerid string, base string) (*CgroupCPUStat, error) {
return CgroupCPUWithContext(context.Background(), containerid, base)
}

func CgroupCPUWithContext(ctx context.Context, containerid string, base string) (*cpu.TimesStat, error) {
func CgroupCPUWithContext(ctx context.Context, containerid string, base string) (*CgroupCPUStat, error) {
return nil, ErrCgroupNotAvailable
}

func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) {
func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
return CgroupCPUDockerWithContext(context.Background(), containerid)
}

func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) {
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
}

Expand Down