github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/daemon/stats.go (about) 1 package daemon 2 3 import ( 4 "encoding/json" 5 "io" 6 7 "github.com/docker/docker/api/types" 8 "github.com/docker/docker/daemon/execdriver" 9 "github.com/docker/libcontainer" 10 "github.com/docker/libcontainer/cgroups" 11 ) 12 13 func (daemon *Daemon) ContainerStats(name string, out io.Writer) error { 14 updates, err := daemon.SubscribeToContainerStats(name) 15 if err != nil { 16 return err 17 } 18 enc := json.NewEncoder(out) 19 for v := range updates { 20 update := v.(*execdriver.ResourceStats) 21 ss := convertToAPITypes(update.Stats) 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(name, updates) 28 return err 29 } 30 } 31 return nil 32 } 33 34 // convertToAPITypes converts the libcontainer.Stats to the api specific 35 // structs. This is done to preserve API compatibility and versioning. 36 func convertToAPITypes(ls *libcontainer.Stats) *types.Stats { 37 s := &types.Stats{} 38 if ls.Interfaces != nil { 39 s.Network = types.Network{} 40 for _, iface := range ls.Interfaces { 41 s.Network.RxBytes += iface.RxBytes 42 s.Network.RxPackets += iface.RxPackets 43 s.Network.RxErrors += iface.RxErrors 44 s.Network.RxDropped += iface.RxDropped 45 s.Network.TxBytes += iface.TxBytes 46 s.Network.TxPackets += iface.TxPackets 47 s.Network.TxErrors += iface.TxErrors 48 s.Network.TxDropped += iface.TxDropped 49 } 50 } 51 cs := ls.CgroupStats 52 if cs != nil { 53 s.BlkioStats = types.BlkioStats{ 54 IoServiceBytesRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceBytesRecursive), 55 IoServicedRecursive: copyBlkioEntry(cs.BlkioStats.IoServicedRecursive), 56 IoQueuedRecursive: copyBlkioEntry(cs.BlkioStats.IoQueuedRecursive), 57 IoServiceTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoServiceTimeRecursive), 58 IoWaitTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoWaitTimeRecursive), 59 IoMergedRecursive: copyBlkioEntry(cs.BlkioStats.IoMergedRecursive), 60 IoTimeRecursive: copyBlkioEntry(cs.BlkioStats.IoTimeRecursive), 61 SectorsRecursive: copyBlkioEntry(cs.BlkioStats.SectorsRecursive), 62 } 63 cpu := cs.CpuStats 64 s.CpuStats = types.CpuStats{ 65 CpuUsage: types.CpuUsage{ 66 TotalUsage: cpu.CpuUsage.TotalUsage, 67 PercpuUsage: cpu.CpuUsage.PercpuUsage, 68 UsageInKernelmode: cpu.CpuUsage.UsageInKernelmode, 69 UsageInUsermode: cpu.CpuUsage.UsageInUsermode, 70 }, 71 ThrottlingData: types.ThrottlingData{ 72 Periods: cpu.ThrottlingData.Periods, 73 ThrottledPeriods: cpu.ThrottlingData.ThrottledPeriods, 74 ThrottledTime: cpu.ThrottlingData.ThrottledTime, 75 }, 76 } 77 mem := cs.MemoryStats 78 s.MemoryStats = types.MemoryStats{ 79 Usage: mem.Usage, 80 MaxUsage: mem.MaxUsage, 81 Stats: mem.Stats, 82 Failcnt: mem.Failcnt, 83 } 84 } 85 return s 86 } 87 88 func copyBlkioEntry(entries []cgroups.BlkioStatEntry) []types.BlkioStatEntry { 89 out := make([]types.BlkioStatEntry, len(entries)) 90 for i, re := range entries { 91 out[i] = types.BlkioStatEntry{ 92 Major: re.Major, 93 Minor: re.Minor, 94 Op: re.Op, 95 Value: re.Value, 96 } 97 } 98 return out 99 }