github.com/dougm/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  }