get docker container cpu usage from cpuacct.usage

pull/581/head
CMGS 7 years ago
parent eb1f1ab16f
commit d93c01e54d

@ -13,7 +13,7 @@ import (
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
) )
var cpu_tick = float64(100) var CPUTick = float64(100)
func init() { func init() {
getconf, err := exec.LookPath("/usr/bin/getconf") getconf, err := exec.LookPath("/usr/bin/getconf")
@ -25,7 +25,7 @@ func init() {
if err == nil { if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64) i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil { if err == nil {
cpu_tick = float64(i) CPUTick = i
} }
} }
} }
@ -251,34 +251,34 @@ func parseStatLine(line string) (*TimesStat, error) {
ct := &TimesStat{ ct := &TimesStat{
CPU: cpu, CPU: cpu,
User: float64(user) / cpu_tick, User: user / CPUTick,
Nice: float64(nice) / cpu_tick, Nice: nice / CPUTick,
System: float64(system) / cpu_tick, System: system / CPUTick,
Idle: float64(idle) / cpu_tick, Idle: idle / CPUTick,
Iowait: float64(iowait) / cpu_tick, Iowait: iowait / CPUTick,
Irq: float64(irq) / cpu_tick, Irq: irq / CPUTick,
Softirq: float64(softirq) / cpu_tick, Softirq: softirq / CPUTick,
} }
if len(fields) > 8 { // Linux >= 2.6.11 if len(fields) > 8 { // Linux >= 2.6.11
steal, err := strconv.ParseFloat(fields[8], 64) steal, err := strconv.ParseFloat(fields[8], 64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ct.Steal = float64(steal) / cpu_tick ct.Steal = steal / CPUTick
} }
if len(fields) > 9 { // Linux >= 2.6.24 if len(fields) > 9 { // Linux >= 2.6.24
guest, err := strconv.ParseFloat(fields[9], 64) guest, err := strconv.ParseFloat(fields[9], 64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ct.Guest = float64(guest) / cpu_tick ct.Guest = guest / CPUTick
} }
if len(fields) > 10 { // Linux >= 3.2.0 if len(fields) > 10 { // Linux >= 3.2.0
guestNice, err := strconv.ParseFloat(fields[10], 64) guestNice, err := strconv.ParseFloat(fields[10], 64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ct.GuestNice = float64(guestNice) / cpu_tick ct.GuestNice = guestNice / CPUTick
} }
return ct, nil return ct, nil

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
) )
@ -12,6 +13,11 @@ var ErrCgroupNotAvailable = errors.New("cgroup not available")
var invoke common.Invoker = common.Invoke{} var invoke common.Invoker = common.Invoke{}
type CgroupCPUStat struct {
cpu.TimesStat
Usage float64
}
type CgroupMemStat struct { type CgroupMemStat struct {
ContainerID string `json:"containerID"` ContainerID string `json:"containerID"`
Cache uint64 `json:"cache"` Cache uint64 `json:"cache"`

@ -89,11 +89,31 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
// containerID is same as docker id if you use docker. // containerID is same as docker id if you use docker.
// If you use container via systemd.slice, you could use // If you use container via systemd.slice, you could use
// containerID = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ // 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) return CgroupCPUWithContext(context.Background(), containerID, base)
} }
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*cpu.TimesStat, error) { func CgroupCPUUsage(containerID string, base string) (float64, error) {
return CgroupCPUUsageWithContext(context.Background(), containerID, base)
}
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 / 1e9, nil
}
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) {
statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat") statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat")
lines, err := common.ReadLines(statfile) lines, err := common.ReadLines(statfile)
if err != nil { if err != nil {
@ -103,31 +123,40 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
if len(containerID) == 0 { if len(containerID) == 0 {
containerID = "all" containerID = "all"
} }
ret := &cpu.TimesStat{CPU: containerID} ret := &CgroupCPUStat{}
ret.CPU = containerID
for _, line := range lines { for _, line := range lines {
fields := strings.Split(line, " ") fields := strings.Split(line, " ")
if fields[0] == "user" { if fields[0] == "user" {
user, err := strconv.ParseFloat(fields[1], 64) user, err := strconv.ParseFloat(fields[1], 64)
if err == nil { if err == nil {
ret.User = float64(user) ret.User = user / cpu.CPUTick
} }
} }
if fields[0] == "system" { if fields[0] == "system" {
system, err := strconv.ParseFloat(fields[1], 64) system, err := strconv.ParseFloat(fields[1], 64)
if err == nil { 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 return ret, nil
} }
func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
return CgroupCPUDockerWithContext(context.Background(), containerid) 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")) return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
} }

@ -4,7 +4,7 @@ package docker
import ( import (
"context" "context"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common" "github.com/shirou/gopsutil/internal/common"
) )
@ -32,19 +32,19 @@ func GetDockerIDListWithContext(ctx context.Context) ([]string, error) {
// containerid is same as docker id if you use docker. // containerid is same as docker id if you use docker.
// If you use container via systemd.slice, you could use // If you use container via systemd.slice, you could use
// containerid = docker-<container id>.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ // 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) 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 return nil, ErrCgroupNotAvailable
} }
func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
return CgroupCPUDockerWithContext(context.Background(), containerid) 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")) return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
} }

Loading…
Cancel
Save