From ab4f9495ba9e3bd31ccb3800f2c574771b86744a Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 2 Feb 2015 11:27:18 -0800 Subject: [PATCH] Print zeros for initial stats collection on stopped container When calling stats on stopped container's print out zeros for all of the values to populate the initial table. This signals to the user that the operations completed and will not block. Closes #10504 Signed-off-by: Michael Crosby --- api/client/commands.go | 49 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/api/client/commands.go b/api/client/commands.go index c9812899a6..3cd110b4ec 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -2614,7 +2614,12 @@ type containerStats struct { err error } -func (s *containerStats) Collect(stream io.ReadCloser) { +func (s *containerStats) Collect(cli *DockerCli) { + stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats", nil, false) + if err != nil { + s.err = err + return + } defer stream.Close() var ( previousCpu uint64 @@ -2694,28 +2699,44 @@ func (cli *DockerCli) CmdStats(args ...string) error { names := cmd.Args() sort.Strings(names) - var cStats []*containerStats - for _, n := range names { - s := &containerStats{Name: n} - cStats = append(cStats, s) - stream, _, err := cli.call("GET", "/containers/"+n+"/stats", nil, false) - if err != nil { - return err - } - go s.Collect(stream) - } - w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - for _ = range time.Tick(500 * time.Millisecond) { + var ( + cStats []*containerStats + w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) + ) + printHeader := func() { fmt.Fprint(cli.out, "\033[2J") fmt.Fprint(cli.out, "\033[H") fmt.Fprintln(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O") + } + for _, n := range names { + s := &containerStats{Name: n} + cStats = append(cStats, s) + go s.Collect(cli) + } + // do a quick pause so that any failed connections for containers that do not exist are able to be + // evicted before we display the initial or default values. + time.Sleep(500 * time.Millisecond) + var errs []string + for _, c := range cStats { + c.mu.Lock() + if c.err != nil { + errs = append(errs, fmt.Sprintf("%s: %s", c.Name, c.err.Error())) + } + c.mu.Unlock() + } + if len(errs) > 0 { + return fmt.Errorf("%s", strings.Join(errs, ", ")) + } + for _ = range time.Tick(500 * time.Millisecond) { + printHeader() toRemove := []int{} for i, s := range cStats { if err := s.Display(w); err != nil { toRemove = append(toRemove, i) } } - for _, i := range toRemove { + for j := len(toRemove) - 1; j >= 0; j-- { + i := toRemove[j] cStats = append(cStats[:i], cStats[i+1:]...) } if len(cStats) == 0 {