Przeglądaj źródła

Add support for Names and ID in stats format

This adds support to display names or id of container instead of what
was provided in the request.

This keeps the default behavior (`docker stats byname` will display
`byname` in the `CONTAINER` colmun and `docker stats byid` will display
the id in the `CONTAINER` column) but adds two new format directive.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Vincent Demeester 8 lat temu
rodzic
commit
ef915fd036

+ 3 - 0
api/types/stats.go

@@ -170,6 +170,9 @@ type Stats struct {
 type StatsJSON struct {
 	Stats
 
+	Name string `json:"name,omitempty"`
+	ID   string `json:"id,omitempty"`
+
 	// Networks request version >=1.21
 	Networks map[string]NetworkStats `json:"networks,omitempty"`
 }

+ 6 - 4
cli/command/container/stats_helpers.go

@@ -29,7 +29,7 @@ var daemonOSType string
 func (s *stats) add(cs *formatter.ContainerStats) bool {
 	s.mu.Lock()
 	defer s.mu.Unlock()
-	if _, exists := s.isKnownContainer(cs.Name); !exists {
+	if _, exists := s.isKnownContainer(cs.Container); !exists {
 		s.cs = append(s.cs, cs)
 		return true
 	}
@@ -46,7 +46,7 @@ func (s *stats) remove(id string) {
 
 func (s *stats) isKnownContainer(cid string) (int, bool) {
 	for i, c := range s.cs {
-		if c.Name == cid {
+		if c.Container == cid {
 			return i, true
 		}
 	}
@@ -54,7 +54,7 @@ func (s *stats) isKnownContainer(cid string) (int, bool) {
 }
 
 func collect(s *formatter.ContainerStats, ctx context.Context, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
-	logrus.Debugf("collecting stats for %s", s.Name)
+	logrus.Debugf("collecting stats for %s", s.Container)
 	var (
 		getFirst       bool
 		previousCPU    uint64
@@ -70,7 +70,7 @@ func collect(s *formatter.ContainerStats, ctx context.Context, cli client.APICli
 		}
 	}()
 
-	response, err := cli.ContainerStats(ctx, s.Name, streamStats)
+	response, err := cli.ContainerStats(ctx, s.Container, streamStats)
 	if err != nil {
 		s.SetError(err)
 		return
@@ -125,6 +125,8 @@ func collect(s *formatter.ContainerStats, ctx context.Context, cli client.APICli
 			}
 			netRx, netTx := calculateNetwork(v.Networks)
 			s.SetStatistics(formatter.StatsEntry{
+				Name:             v.Name,
+				ID:               v.ID,
 				CPUPercentage:    cpuPercent,
 				Memory:           mem,
 				MemoryPercentage: memPerc,

+ 17 - 4
cli/command/formatter/stats.go

@@ -24,7 +24,9 @@ const (
 
 // StatsEntry represents represents the statistics data collected from a container
 type StatsEntry struct {
+	Container        string
 	Name             string
+	ID               string
 	CPUPercentage    float64
 	Memory           float64 // On Windows this is the private working set
 	MemoryLimit      float64 // Not used on Windows
@@ -85,7 +87,7 @@ func (cs *ContainerStats) SetError(err error) {
 func (cs *ContainerStats) SetStatistics(s StatsEntry) {
 	cs.mutex.Lock()
 	defer cs.mutex.Unlock()
-	s.Name = cs.Name
+	s.Container = cs.Container
 	s.OSType = cs.OSType
 	cs.StatsEntry = s
 }
@@ -109,9 +111,9 @@ func NewStatsFormat(source, osType string) Format {
 }
 
 // NewContainerStats returns a new ContainerStats entity and sets in it the given name
-func NewContainerStats(name, osType string) *ContainerStats {
+func NewContainerStats(container, osType string) *ContainerStats {
 	return &ContainerStats{
-		StatsEntry: StatsEntry{Name: name, OSType: osType},
+		StatsEntry: StatsEntry{Container: container, OSType: osType},
 	}
 }
 
@@ -138,7 +140,18 @@ type containerStatsContext struct {
 
 func (c *containerStatsContext) Container() string {
 	c.AddHeader(containerHeader)
-	return c.s.Name
+	return c.s.Container
+}
+
+func (c *containerStatsContext) Name() string {
+	c.AddHeader(nameHeader)
+	name := c.s.Name[1:]
+	return name
+}
+
+func (c *containerStatsContext) ID() string {
+	c.AddHeader(containerIDHeader)
+	return c.s.ID
 }
 
 func (c *containerStatsContext) CPUPerc() string {

+ 5 - 5
cli/command/formatter/stats_test.go

@@ -18,7 +18,7 @@ func TestContainerStatsContext(t *testing.T) {
 		expHeader string
 		call      func() string
 	}{
-		{StatsEntry{Name: containerID}, containerID, containerHeader, ctx.Container},
+		{StatsEntry{Container: containerID}, containerID, containerHeader, ctx.Container},
 		{StatsEntry{CPUPercentage: 5.5}, "5.50%", cpuPercHeader, ctx.CPUPerc},
 		{StatsEntry{CPUPercentage: 5.5, IsInvalid: true}, "--", cpuPercHeader, ctx.CPUPerc},
 		{StatsEntry{NetworkRx: 0.31, NetworkTx: 12.3}, "0.31 B / 12.3 B", netIOHeader, ctx.NetIO},
@@ -82,7 +82,7 @@ container2  --
 	for _, te := range tt {
 		stats := []StatsEntry{
 			{
-				Name:             "container1",
+				Container:        "container1",
 				CPUPercentage:    20,
 				Memory:           20,
 				MemoryLimit:      20,
@@ -96,7 +96,7 @@ container2  --
 				OSType:           "linux",
 			},
 			{
-				Name:             "container2",
+				Container:        "container2",
 				CPUPercentage:    30,
 				Memory:           30,
 				MemoryLimit:      30,
@@ -150,7 +150,7 @@ container2  --  --
 	for _, te := range tt {
 		stats := []StatsEntry{
 			{
-				Name:             "container1",
+				Container:        "container1",
 				CPUPercentage:    20,
 				Memory:           20,
 				MemoryLimit:      20,
@@ -164,7 +164,7 @@ container2  --  --
 				OSType:           "windows",
 			},
 			{
-				Name:             "container2",
+				Container:        "container2",
 				CPUPercentage:    30,
 				Memory:           30,
 				MemoryLimit:      30,

+ 2 - 0
daemon/stats.go

@@ -44,6 +44,8 @@ func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, c
 	var preRead time.Time
 	getStatJSON := func(v interface{}) *types.StatsJSON {
 		ss := v.(types.StatsJSON)
+		ss.Name = container.Name
+		ss.ID = container.ID
 		ss.PreCPUStats = preCPUStats
 		ss.PreRead = preRead
 		preCPUStats = ss.CPUStats