From 5dc3a9a6da6ce6e3eee791251293cf045a4754f9 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 3 Nov 2015 14:06:16 -0500 Subject: [PATCH] Decouple daemon and container from the stats collector. Signed-off-by: David Calavera --- daemon/container.go | 4 --- daemon/daemon.go | 54 +++++++++++++++++++++++++++++++++- daemon/stats_collector_unix.go | 51 ++++++-------------------------- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index f4c6b84d85..95da662276 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -338,10 +338,6 @@ func (container *Container) getMountLabel() string { return container.MountLabel } -func (container *Container) stats() (*execdriver.ResourceStats, error) { - return container.daemon.stats(container) -} - func (container *Container) getExecIDs() []string { return container.execCommands.List() } diff --git a/daemon/daemon.go b/daemon/daemon.go index d902028163..de9a1157c2 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -56,6 +56,8 @@ import ( "github.com/docker/docker/volume/local" "github.com/docker/docker/volume/store" "github.com/docker/libnetwork" + lntypes "github.com/docker/libnetwork/types" + "github.com/opencontainers/runc/libcontainer" ) var ( @@ -816,7 +818,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo d.configStore = config d.sysInitPath = sysInitPath d.execDriver = ed - d.statsCollector = newStatsCollector(1 * time.Second) + d.statsCollector = d.newStatsCollector(1 * time.Second) d.defaultLogConfig = config.LogConfig d.RegistryService = registryService d.EventsService = eventsService @@ -1300,3 +1302,53 @@ func (daemon *Daemon) SearchRegistryForImages(term string, headers map[string][]string) (*registry.SearchResults, error) { return daemon.RegistryService.Search(term, authConfig, headers) } + +func (daemon *Daemon) GetContainerStats(container *Container) (*execdriver.ResourceStats, error) { + stats, err := daemon.stats(container) + if err != nil { + return nil, err + } + + // Retrieve the nw statistics from libnetwork and inject them in the Stats + var nwStats []*libcontainer.NetworkInterface + if nwStats, err = daemon.getNetworkStats(container); err != nil { + return nil, err + } + stats.Interfaces = nwStats + + return stats, nil +} + +func (daemon *Daemon) getNetworkStats(c *Container) ([]*libcontainer.NetworkInterface, error) { + var list []*libcontainer.NetworkInterface + + sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID) + if err != nil { + return list, err + } + + stats, err := sb.Statistics() + if err != nil { + return list, err + } + + // Convert libnetwork nw stats into libcontainer nw stats + for ifName, ifStats := range stats { + list = append(list, convertLnNetworkStats(ifName, ifStats)) + } + + return list, nil +} + +func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *libcontainer.NetworkInterface { + n := &libcontainer.NetworkInterface{Name: name} + n.RxBytes = stats.RxBytes + n.RxPackets = stats.RxPackets + n.RxErrors = stats.RxErrors + n.RxDropped = stats.RxDropped + n.TxBytes = stats.TxBytes + n.TxPackets = stats.TxPackets + n.TxErrors = stats.TxErrors + n.TxDropped = stats.TxDropped + return n +} diff --git a/daemon/stats_collector_unix.go b/daemon/stats_collector_unix.go index 827578b6f2..6fb32b9a22 100644 --- a/daemon/stats_collector_unix.go +++ b/daemon/stats_collector_unix.go @@ -14,18 +14,22 @@ import ( "github.com/docker/docker/daemon/execdriver" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/pubsub" - lntypes "github.com/docker/libnetwork/types" - "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/system" ) +type statsSupervisor interface { + // GetContainerStats collects all the stats related to a container + GetContainerStats(container *Container) (*execdriver.ResourceStats, error) +} + // newStatsCollector returns a new statsCollector that collections // network and cgroup stats for a registered container at the specified // interval. The collector allows non-running containers to be added // and will start processing stats when they are started. -func newStatsCollector(interval time.Duration) *statsCollector { +func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector { s := &statsCollector{ interval: interval, + supervisor: daemon, publishers: make(map[*Container]*pubsub.Publisher), clockTicksPerSecond: uint64(system.GetClockTicks()), bufReader: bufio.NewReaderSize(nil, 128), @@ -37,6 +41,7 @@ func newStatsCollector(interval time.Duration) *statsCollector { // statsCollector manages and provides container resource stats type statsCollector struct { m sync.Mutex + supervisor statsSupervisor interval time.Duration clockTicksPerSecond uint64 publishers map[*Container]*pubsub.Publisher @@ -112,7 +117,7 @@ func (s *statsCollector) run() { } for _, pair := range pairs { - stats, err := pair.container.stats() + stats, err := s.supervisor.GetContainerStats(pair.container) if err != nil { if err != execdriver.ErrNotRunning { logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err) @@ -121,10 +126,6 @@ func (s *statsCollector) run() { } stats.SystemUsage = systemUsage - // Retrieve the nw statistics from libnetwork and inject them in the Stats - if nwStats, err := s.getNetworkStats(pair.container); err == nil { - stats.Interfaces = nwStats - } pair.publisher.Publish(stats) } } @@ -177,37 +178,3 @@ func (s *statsCollector) getSystemCPUUsage() (uint64, error) { } return 0, derr.ErrorCodeBadStatFormat } - -func (s *statsCollector) getNetworkStats(c *Container) ([]*libcontainer.NetworkInterface, error) { - var list []*libcontainer.NetworkInterface - - sb, err := c.daemon.netController.SandboxByID(c.NetworkSettings.SandboxID) - if err != nil { - return list, err - } - - stats, err := sb.Statistics() - if err != nil { - return list, err - } - - // Convert libnetwork nw stats into libcontainer nw stats - for ifName, ifStats := range stats { - list = append(list, convertLnNetworkStats(ifName, ifStats)) - } - - return list, nil -} - -func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *libcontainer.NetworkInterface { - n := &libcontainer.NetworkInterface{Name: name} - n.RxBytes = stats.RxBytes - n.RxPackets = stats.RxPackets - n.RxErrors = stats.RxErrors - n.RxDropped = stats.RxDropped - n.TxBytes = stats.TxBytes - n.TxPackets = stats.TxPackets - n.TxErrors = stats.TxErrors - n.TxDropped = stats.TxDropped - return n -}