Merge pull request #780 from crosbymichael/stats-format

Improve stats output format for stability
This commit is contained in:
Qiang Huang 2016-04-26 17:16:53 +08:00
commit 5c1ea321df
1 changed files with 147 additions and 3 deletions

150
events.go
View File

@ -11,6 +11,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/cgroups"
)
// event struct for encoding the event data to json.
@ -20,9 +21,82 @@ type event struct {
Data interface{} `json:"data,omitempty"`
}
// stats is the runc specific stats structure for stability when encoding and decoding stats.
type stats struct {
Cpu cpu `json:"cpu"`
Memory memory `json:"memory"`
Pids pids `json:"pids"`
Blkio blkio `json:"blkio"`
Hugetlb map[string]hugetlb `json:"hugetlb"`
}
type hugetlb struct {
Usage uint64 `json:"usage,omitempty"`
Max uint64 `json:"max,omitempty"`
Failcnt uint64 `json:"failcnt"`
}
type blkioEntry struct {
Major uint64 `json:"major,omitempty"`
Minor uint64 `json:"minor,omitempty"`
Op string `json:"op,omitempty"`
Value uint64 `json:"value,omitempty"`
}
type blkio struct {
IoServiceBytesRecursive []blkioEntry `json:"ioServiceBytesRecursive,omitempty"`
IoServicedRecursive []blkioEntry `json:"ioServicedRecursive,omitempty"`
IoQueuedRecursive []blkioEntry `json:"ioQueueRecursive,omitempty"`
IoServiceTimeRecursive []blkioEntry `json:"ioServiceTimeRecursive,omitempty"`
IoWaitTimeRecursive []blkioEntry `json:"ioWaitTimeRecursive,omitempty"`
IoMergedRecursive []blkioEntry `json:"ioMergedRecursive,omitempty"`
IoTimeRecursive []blkioEntry `json:"ioTimeRecursive,omitempty"`
SectorsRecursive []blkioEntry `json:"sectorsRecursive,omitempty"`
}
type pids struct {
Current uint64 `json:"current,omitempty"`
Limit uint64 `json:"limit,omitempty"`
}
type throttling struct {
Periods uint64 `json:"periods,omitempty"`
ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"`
ThrottledTime uint64 `json:"throttledTime,omitempty"`
}
type cpuUsage struct {
// Units: nanoseconds.
Total uint64 `json:"total,omitempty"`
Percpu []uint64 `json:"percpu,omitempty"`
Kernel uint64 `json:"kernel"`
User uint64 `json:"user"`
}
type cpu struct {
Usage cpuUsage `json:"usage,omitempty"`
Throttling throttling `json:"throttling,omitempty"`
}
type memoryEntry struct {
Limit uint64 `json:"limit"`
Usage uint64 `json:"usage,omitempty"`
Max uint64 `json:"max,omitempty"`
Failcnt uint64 `json:"failcnt"`
}
type memory struct {
Cache uint64 `json:"cache,omitempty"`
Usage memoryEntry `json:"usage,omitempty"`
Swap memoryEntry `json:"swap,omitempty"`
Kernel memoryEntry `json:"kernel,omitempty"`
KernelTCP memoryEntry `json:"kernelTCP,omitempty"`
Raw map[string]uint64 `json:"raw,omitempty"`
}
var eventsCommand = cli.Command{
Name: "events",
Usage: "display container events such as OOM notifications, cpu, memory, IO and network stats",
Usage: "display container events such as OOM notifications, cpu, memory, and IO usage statistics",
ArgsUsage: `<container-id>
Where "<container-id>" is the name for the instance of the container.`,
@ -64,7 +138,7 @@ information is displayed once every 5 seconds.`,
if err != nil {
fatal(err)
}
events <- &event{Type: "stats", ID: container.ID(), Data: s}
events <- &event{Type: "stats", ID: container.ID(), Data: convertLibcontainerStats(s)}
close(events)
group.Wait()
return
@ -95,7 +169,7 @@ information is displayed once every 5 seconds.`,
n = nil
}
case s := <-stats:
events <- &event{Type: "stats", ID: container.ID(), Data: s}
events <- &event{Type: "stats", ID: container.ID(), Data: convertLibcontainerStats(s)}
}
if n == nil {
close(events)
@ -105,3 +179,73 @@ information is displayed once every 5 seconds.`,
group.Wait()
},
}
func convertLibcontainerStats(ls *libcontainer.Stats) *stats {
cg := ls.CgroupStats
if cg == nil {
return nil
}
var s stats
s.Pids.Current = cg.PidsStats.Current
s.Pids.Limit = cg.PidsStats.Limit
s.Cpu.Usage.Kernel = cg.CpuStats.CpuUsage.UsageInKernelmode
s.Cpu.Usage.User = cg.CpuStats.CpuUsage.UsageInUsermode
s.Cpu.Usage.Total = cg.CpuStats.CpuUsage.TotalUsage
s.Cpu.Usage.Percpu = cg.CpuStats.CpuUsage.PercpuUsage
s.Cpu.Throttling.Periods = cg.CpuStats.ThrottlingData.Periods
s.Cpu.Throttling.ThrottledPeriods = cg.CpuStats.ThrottlingData.ThrottledPeriods
s.Cpu.Throttling.ThrottledTime = cg.CpuStats.ThrottlingData.ThrottledTime
s.Memory.Cache = cg.MemoryStats.Cache
s.Memory.Kernel = convertMemoryEntry(cg.MemoryStats.KernelUsage)
s.Memory.KernelTCP = convertMemoryEntry(cg.MemoryStats.KernelTCPUsage)
s.Memory.Swap = convertMemoryEntry(cg.MemoryStats.SwapUsage)
s.Memory.Usage = convertMemoryEntry(cg.MemoryStats.Usage)
s.Memory.Raw = cg.MemoryStats.Stats
s.Blkio.IoServiceBytesRecursive = convertBlkioEntry(cg.BlkioStats.IoServiceBytesRecursive)
s.Blkio.IoServicedRecursive = convertBlkioEntry(cg.BlkioStats.IoServicedRecursive)
s.Blkio.IoQueuedRecursive = convertBlkioEntry(cg.BlkioStats.IoQueuedRecursive)
s.Blkio.IoServiceTimeRecursive = convertBlkioEntry(cg.BlkioStats.IoServiceTimeRecursive)
s.Blkio.IoWaitTimeRecursive = convertBlkioEntry(cg.BlkioStats.IoWaitTimeRecursive)
s.Blkio.IoMergedRecursive = convertBlkioEntry(cg.BlkioStats.IoMergedRecursive)
s.Blkio.IoTimeRecursive = convertBlkioEntry(cg.BlkioStats.IoTimeRecursive)
s.Blkio.SectorsRecursive = convertBlkioEntry(cg.BlkioStats.SectorsRecursive)
s.Hugetlb = make(map[string]hugetlb)
for k, v := range cg.HugetlbStats {
s.Hugetlb[k] = convertHugtlb(v)
}
return &s
}
func convertHugtlb(c cgroups.HugetlbStats) hugetlb {
return hugetlb{
Usage: c.Usage,
Max: c.MaxUsage,
Failcnt: c.Failcnt,
}
}
func convertMemoryEntry(c cgroups.MemoryData) memoryEntry {
return memoryEntry{
Limit: c.Limit,
Usage: c.Usage,
Max: c.MaxUsage,
Failcnt: c.Failcnt,
}
}
func convertBlkioEntry(c []cgroups.BlkioStatEntry) []blkioEntry {
var out []blkioEntry
for _, e := range c {
out = append(out, blkioEntry{
Major: e.Major,
Minor: e.Minor,
Op: e.Op,
Value: e.Value,
})
}
return out
}