github.com/akashshinde/docker@v1.9.1/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/api/types/versions/v1p20"
     9  	"github.com/docker/docker/daemon/execdriver"
    10  	"github.com/docker/docker/pkg/version"
    11  )
    12  
    13  // ContainerStatsConfig holds information for configuring the runtime
    14  // behavior of a daemon.ContainerStats() call.
    15  type ContainerStatsConfig struct {
    16  	Stream    bool
    17  	OutStream io.Writer
    18  	Stop      <-chan bool
    19  	Version   version.Version
    20  }
    21  
    22  // ContainerStats writes information about the container to the stream
    23  // given in the config object.
    24  func (daemon *Daemon) ContainerStats(prefixOrName string, config *ContainerStatsConfig) error {
    25  
    26  	container, err := daemon.Get(prefixOrName)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	// If the container is not running and requires no stream, return an empty stats.
    32  	if !container.IsRunning() && !config.Stream {
    33  		return json.NewEncoder(config.OutStream).Encode(&types.Stats{})
    34  	}
    35  
    36  	updates, err := daemon.subscribeToContainerStats(container)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	if config.Stream {
    42  		// Write an empty chunk of data.
    43  		// This is to ensure that the HTTP status code is sent immediately,
    44  		// even if the container has not yet produced any data.
    45  		config.OutStream.Write(nil)
    46  	}
    47  
    48  	var preCPUStats types.CPUStats
    49  	getStatJSON := func(v interface{}) *types.StatsJSON {
    50  		update := v.(*execdriver.ResourceStats)
    51  		ss := convertStatsToAPITypes(update.Stats)
    52  		ss.PreCPUStats = preCPUStats
    53  		ss.MemoryStats.Limit = uint64(update.MemoryLimit)
    54  		ss.Read = update.Read
    55  		ss.CPUStats.SystemUsage = update.SystemUsage
    56  		preCPUStats = ss.CPUStats
    57  		return ss
    58  	}
    59  
    60  	enc := json.NewEncoder(config.OutStream)
    61  
    62  	defer daemon.unsubscribeToContainerStats(container, updates)
    63  
    64  	noStreamFirstFrame := true
    65  	for {
    66  		select {
    67  		case v, ok := <-updates:
    68  			if !ok {
    69  				return nil
    70  			}
    71  
    72  			var statsJSON interface{}
    73  			statsJSONPost120 := getStatJSON(v)
    74  			if config.Version.LessThan("1.21") {
    75  				var (
    76  					rxBytes   uint64
    77  					rxPackets uint64
    78  					rxErrors  uint64
    79  					rxDropped uint64
    80  					txBytes   uint64
    81  					txPackets uint64
    82  					txErrors  uint64
    83  					txDropped uint64
    84  				)
    85  				for _, v := range statsJSONPost120.Networks {
    86  					rxBytes += v.RxBytes
    87  					rxPackets += v.RxPackets
    88  					rxErrors += v.RxErrors
    89  					rxDropped += v.RxDropped
    90  					txBytes += v.TxBytes
    91  					txPackets += v.TxPackets
    92  					txErrors += v.TxErrors
    93  					txDropped += v.TxDropped
    94  				}
    95  				statsJSON = &v1p20.StatsJSON{
    96  					Stats: statsJSONPost120.Stats,
    97  					Network: types.NetworkStats{
    98  						RxBytes:   rxBytes,
    99  						RxPackets: rxPackets,
   100  						RxErrors:  rxErrors,
   101  						RxDropped: rxDropped,
   102  						TxBytes:   txBytes,
   103  						TxPackets: txPackets,
   104  						TxErrors:  txErrors,
   105  						TxDropped: txDropped,
   106  					},
   107  				}
   108  			} else {
   109  				statsJSON = statsJSONPost120
   110  			}
   111  
   112  			if !config.Stream && noStreamFirstFrame {
   113  				// prime the cpu stats so they aren't 0 in the final output
   114  				noStreamFirstFrame = false
   115  				continue
   116  			}
   117  
   118  			if err := enc.Encode(statsJSON); err != nil {
   119  				return err
   120  			}
   121  
   122  			if !config.Stream {
   123  				return nil
   124  			}
   125  		case <-config.Stop:
   126  			return nil
   127  		}
   128  	}
   129  }