Kaynağa Gözat

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 <crosbymichael@gmail.com>
Michael Crosby 10 yıl önce
ebeveyn
işleme
ab4f9495ba
1 değiştirilmiş dosya ile 32 ekleme ve 11 silme
  1. 32 11
      api/client/commands.go

+ 32 - 11
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
+	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)
-		stream, _, err := cli.call("GET", "/containers/"+n+"/stats", nil, false)
-		if err != nil {
-			return err
+		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()))
 		}
-		go s.Collect(stream)
+		c.mu.Unlock()
+	}
+	if len(errs) > 0 {
+		return fmt.Errorf("%s", strings.Join(errs, ", "))
 	}
-	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
 	for _ = range time.Tick(500 * time.Millisecond) {
-		fmt.Fprint(cli.out, "\033[2J")
-		fmt.Fprint(cli.out, "\033[H")
-		fmt.Fprintln(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O")
+		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 {