Browse code

Return an empty stats if "container not found"

If we get "container not found" error from containerd, it's possibly
because that this container has already been stopped. It will be ok to
ignore this error and just return an empty stats.

Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>

Yuanhong Peng authored on 2017/07/07 16:33:45
Showing 4 changed files
... ...
@@ -1165,6 +1165,9 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
1165 1165
 	}
1166 1166
 	stats, err := daemon.containerd.Stats(c.ID)
1167 1167
 	if err != nil {
1168
+		if strings.Contains(err.Error(), "container not found") {
1169
+			return nil, errNotFound{c.ID}
1170
+		}
1168 1171
 		return nil, err
1169 1172
 	}
1170 1173
 	s := &types.StatsJSON{}
... ...
@@ -525,6 +525,9 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
525 525
 	// Obtain the stats from HCS via libcontainerd
526 526
 	stats, err := daemon.containerd.Stats(c.ID)
527 527
 	if err != nil {
528
+		if strings.Contains(err.Error(), "container not found") {
529
+			return nil, errNotFound{c.ID}
530
+		}
528 531
 		return nil, err
529 532
 	}
530 533
 
... ...
@@ -39,3 +39,15 @@ func errExecPaused(id string) error {
39 39
 	err := fmt.Errorf("Container %s is paused, unpause the container before exec", id)
40 40
 	return errors.NewRequestConflictError(err)
41 41
 }
42
+
43
+type errNotFound struct {
44
+	containerID string
45
+}
46
+
47
+func (e errNotFound) Error() string {
48
+	return fmt.Sprintf("Container %s is not found", e.containerID)
49
+}
50
+
51
+func (e errNotFound) ContainerNotFound() bool {
52
+	return true
53
+}
... ...
@@ -88,24 +88,25 @@ func (s *Collector) Run() {
88 88
 
89 89
 		for _, pair := range pairs {
90 90
 			stats, err := s.supervisor.GetContainerStats(pair.container)
91
-			if err != nil {
92
-				if _, ok := err.(notRunningErr); !ok {
93
-					logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
94
-					continue
95
-				}
96 91
 
97
-				// publish empty stats containing only name and ID if not running
92
+			switch err.(type) {
93
+			case nil:
94
+				// FIXME: move to containerd on Linux (not Windows)
95
+				stats.CPUStats.SystemUsage = systemUsage
96
+				stats.CPUStats.OnlineCPUs = onlineCPUs
97
+
98
+				pair.publisher.Publish(*stats)
99
+
100
+			case notRunningErr, notFoundErr:
101
+				// publish empty stats containing only name and ID if not running or not found
98 102
 				pair.publisher.Publish(types.StatsJSON{
99 103
 					Name: pair.container.Name,
100 104
 					ID:   pair.container.ID,
101 105
 				})
102
-				continue
103
-			}
104
-			// FIXME: move to containerd on Linux (not Windows)
105
-			stats.CPUStats.SystemUsage = systemUsage
106
-			stats.CPUStats.OnlineCPUs = onlineCPUs
107 106
 
108
-			pair.publisher.Publish(*stats)
107
+			default:
108
+				logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
109
+			}
109 110
 		}
110 111
 	}
111 112
 }
... ...
@@ -114,3 +115,8 @@ type notRunningErr interface {
114 114
 	error
115 115
 	ContainerIsRunning() bool
116 116
 }
117
+
118
+type notFoundErr interface {
119
+	error
120
+	ContainerNotFound() bool
121
+}