github.com/oyvindsk/docker@v1.5.0/daemon/stats.go (about) 1 package daemon 2 3 import ( 4 "encoding/json" 5 6 "github.com/docker/docker/api/stats" 7 "github.com/docker/docker/daemon/execdriver" 8 "github.com/docker/docker/engine" 9 "github.com/docker/libcontainer" 10 "github.com/docker/libcontainer/cgroups" 11 ) 12 13 func (daemon *Daemon) ContainerStats(job *engine.Job) engine.Status { 14 updates, err := daemon.SubscribeToContainerStats(job.Args[0]) 15 if err != nil { 16 return job.Error(err) 17 } 18 enc := json.NewEncoder(job.Stdout) 19 for v := range updates { 20 update := v.(*execdriver.ResourceStats) 21 ss := convertToAPITypes(update.ContainerStats) 22 ss.MemoryStats.Limit = uint64(update.MemoryLimit) 23 ss.Read = update.Read 24 ss.CpuStats.SystemUsage = update.SystemUsage 25 if err := enc.Encode(ss); err != nil { 26 // TODO: handle the specific broken pipe 27 daemon.UnsubscribeToContainerStats(job.Args[0], updates) 28 return job.Error(err) 29 } 30 } 31 return engine.StatusOK 32 } 33 34 // convertToAPITypes converts the libcontainer.ContainerStats to the api specific 35 // structs. This is done to preserve API compatibility and versioning. 36 func convertToAPITypes(ls *libcontainer.ContainerStats) *stats.Stats { 37 s := &stats.Stats{} 38 if ls.NetworkStats != nil { 39 s.Network = stats.Network{ 40 RxBytes: ls.NetworkStats.RxBytes, 41 RxPackets: ls.NetworkStats.RxPackets, 42 RxErrors: ls.NetworkStats.RxErrors, 43 RxDropped: ls.NetworkStats.RxDropped, 44 TxBytes: ls.NetworkStats.TxBytes, 45 TxPackets: ls.NetworkStats.TxPackets, 46 TxErrors: ls.NetworkStats.TxErrors, 47 TxDropped: ls.NetworkStats.TxDropped, 48 } 49 } 50 cs := ls.CgroupStats 51 if cs != nil { 52 s.BlkioStats = stats.BlkioStats{ 53 IoServiceBytesRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceBytesRecursive), 54 IoServicedRecursive: copyBlkioEntry(cs.BlkioStats.IoServicedRecursive), 55 IoQueuedRecursive: copyBlkioEntry(cs.BlkioStats.IoQueuedRecursive), 56 IoServiceTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceTimeRecursive), 57 IoWaitTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoWaitTimeRecursive), 58 IoMergedRecursive: copyBlkioEntry(cs.BlkioStats.IoMergedRecursive), 59 IoTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoTimeRecursive), 60 SectorsRecursive: copyBlkioEntry(cs.BlkioStats.SectorsRecursive), 61 } 62 cpu := cs.CpuStats 63 s.CpuStats = stats.CpuStats{ 64 CpuUsage: stats.CpuUsage{ 65 TotalUsage: cpu.CpuUsage.TotalUsage, 66 PercpuUsage: cpu.CpuUsage.PercpuUsage, 67 UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode, 68 UsageInUsermode: cpu.CpuUsage.UsageInUsermode, 69 }, 70 ThrottlingData: stats.ThrottlingData{ 71 Periods: cpu.ThrottlingData.Periods, 72 ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods, 73 ThrottledTime: cpu.ThrottlingData.ThrottledTime, 74 }, 75 } 76 mem := cs.MemoryStats 77 s.MemoryStats = stats.MemoryStats{ 78 Usage: mem.Usage, 79 MaxUsage: mem.MaxUsage, 80 Stats: mem.Stats, 81 Failcnt: mem.Failcnt, 82 } 83 } 84 return s 85 } 86 87 func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []stats.BlkioStatEntry { 88 out := make([]stats.BlkioStatEntry, len(entries)) 89 for i, re := range entries { 90 out[i] = stats.BlkioStatEntry{ 91 Major: re.Major, 92 Minor: re.Minor, 93 Op: re.Op, 94 Value: re.Value, 95 } 96 } 97 return out 98 }