github.com/akerouanton/docker@v1.11.0-rc3/daemon/stats.go (about) 1 package daemon 2 3 import ( 4 "encoding/json" 5 "errors" 6 "runtime" 7 8 "github.com/docker/docker/api/types/backend" 9 "github.com/docker/docker/pkg/ioutils" 10 "github.com/docker/docker/pkg/version" 11 "github.com/docker/engine-api/types" 12 "github.com/docker/engine-api/types/versions/v1p20" 13 ) 14 15 // ContainerStats writes information about the container to the stream 16 // given in the config object. 17 func (daemon *Daemon) ContainerStats(prefixOrName string, config *backend.ContainerStatsConfig) error { 18 if runtime.GOOS == "windows" { 19 return errors.New("Windows does not support stats") 20 } 21 // Remote API version (used for backwards compatibility) 22 apiVersion := version.Version(config.Version) 23 24 container, err := daemon.GetContainer(prefixOrName) 25 if err != nil { 26 return err 27 } 28 29 // If the container is not running and requires no stream, return an empty stats. 30 if !container.IsRunning() && !config.Stream { 31 return json.NewEncoder(config.OutStream).Encode(&types.Stats{}) 32 } 33 34 outStream := config.OutStream 35 if config.Stream { 36 wf := ioutils.NewWriteFlusher(outStream) 37 defer wf.Close() 38 wf.Flush() 39 outStream = wf 40 } 41 42 var preCPUStats types.CPUStats 43 getStatJSON := func(v interface{}) *types.StatsJSON { 44 ss := v.(*types.StatsJSON) 45 ss.PreCPUStats = preCPUStats 46 // ss.MemoryStats.Limit = uint64(update.MemoryLimit) 47 preCPUStats = ss.CPUStats 48 return ss 49 } 50 51 enc := json.NewEncoder(outStream) 52 53 updates := daemon.subscribeToContainerStats(container) 54 defer daemon.unsubscribeToContainerStats(container, updates) 55 56 noStreamFirstFrame := true 57 for { 58 select { 59 case v, ok := <-updates: 60 if !ok { 61 return nil 62 } 63 64 var statsJSON interface{} 65 statsJSONPost120 := getStatJSON(v) 66 if apiVersion.LessThan("1.21") { 67 var ( 68 rxBytes uint64 69 rxPackets uint64 70 rxErrors uint64 71 rxDropped uint64 72 txBytes uint64 73 txPackets uint64 74 txErrors uint64 75 txDropped uint64 76 ) 77 for _, v := range statsJSONPost120.Networks { 78 rxBytes += v.RxBytes 79 rxPackets += v.RxPackets 80 rxErrors += v.RxErrors 81 rxDropped += v.RxDropped 82 txBytes += v.TxBytes 83 txPackets += v.TxPackets 84 txErrors += v.TxErrors 85 txDropped += v.TxDropped 86 } 87 statsJSON = &v1p20.StatsJSON{ 88 Stats: statsJSONPost120.Stats, 89 Network: types.NetworkStats{ 90 RxBytes: rxBytes, 91 RxPackets: rxPackets, 92 RxErrors: rxErrors, 93 RxDropped: rxDropped, 94 TxBytes: txBytes, 95 TxPackets: txPackets, 96 TxErrors: txErrors, 97 TxDropped: txDropped, 98 }, 99 } 100 } else { 101 statsJSON = statsJSONPost120 102 } 103 104 if !config.Stream && noStreamFirstFrame { 105 // prime the cpu stats so they aren't 0 in the final output 106 noStreamFirstFrame = false 107 continue 108 } 109 110 if err := enc.Encode(statsJSON); err != nil { 111 return err 112 } 113 114 if !config.Stream { 115 return nil 116 } 117 case <-config.Stop: 118 return nil 119 } 120 } 121 }