Browse Source

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 years ago
parent
commit
ef915fd036

+ 3 - 0
api/types/stats.go

@@ -170,6 +170,9 @@ type Stats struct {
 type StatsJSON struct {
 type StatsJSON struct {
 	Stats
 	Stats
 
 
+	Name string `json:"name,omitempty"`
+	ID   string `json:"id,omitempty"`
+
 	// Networks request version >=1.21
 	// Networks request version >=1.21
 	Networks map[string]NetworkStats `json:"networks,omitempty"`
 	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 {
 func (s *stats) add(cs *formatter.ContainerStats) bool {
 	s.mu.Lock()
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	defer s.mu.Unlock()
-	if _, exists := s.isKnownContainer(cs.Name); !exists {
+	if _, exists := s.isKnownContainer(cs.Container); !exists {
 		s.cs = append(s.cs, cs)
 		s.cs = append(s.cs, cs)
 		return true
 		return true
 	}
 	}
@@ -46,7 +46,7 @@ func (s *stats) remove(id string) {
 
 
 func (s *stats) isKnownContainer(cid string) (int, bool) {
 func (s *stats) isKnownContainer(cid string) (int, bool) {
 	for i, c := range s.cs {
 	for i, c := range s.cs {
-		if c.Name == cid {
+		if c.Container == cid {
 			return i, true
 			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) {
 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 (
 	var (
 		getFirst       bool
 		getFirst       bool
 		previousCPU    uint64
 		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 {
 	if err != nil {
 		s.SetError(err)
 		s.SetError(err)
 		return
 		return
@@ -125,6 +125,8 @@ func collect(s *formatter.ContainerStats, ctx context.Context, cli client.APICli
 			}
 			}
 			netRx, netTx := calculateNetwork(v.Networks)
 			netRx, netTx := calculateNetwork(v.Networks)
 			s.SetStatistics(formatter.StatsEntry{
 			s.SetStatistics(formatter.StatsEntry{
+				Name:             v.Name,
+				ID:               v.ID,
 				CPUPercentage:    cpuPercent,
 				CPUPercentage:    cpuPercent,
 				Memory:           mem,
 				Memory:           mem,
 				MemoryPercentage: memPerc,
 				MemoryPercentage: memPerc,

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

@@ -24,7 +24,9 @@ const (
 
 
 // StatsEntry represents represents the statistics data collected from a container
 // StatsEntry represents represents the statistics data collected from a container
 type StatsEntry struct {
 type StatsEntry struct {
+	Container        string
 	Name             string
 	Name             string
+	ID               string
 	CPUPercentage    float64
 	CPUPercentage    float64
 	Memory           float64 // On Windows this is the private working set
 	Memory           float64 // On Windows this is the private working set
 	MemoryLimit      float64 // Not used on Windows
 	MemoryLimit      float64 // Not used on Windows
@@ -85,7 +87,7 @@ func (cs *ContainerStats) SetError(err error) {
 func (cs *ContainerStats) SetStatistics(s StatsEntry) {
 func (cs *ContainerStats) SetStatistics(s StatsEntry) {
 	cs.mutex.Lock()
 	cs.mutex.Lock()
 	defer cs.mutex.Unlock()
 	defer cs.mutex.Unlock()
-	s.Name = cs.Name
+	s.Container = cs.Container
 	s.OSType = cs.OSType
 	s.OSType = cs.OSType
 	cs.StatsEntry = s
 	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
 // 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{
 	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 {
 func (c *containerStatsContext) Container() string {
 	c.AddHeader(containerHeader)
 	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 {
 func (c *containerStatsContext) CPUPerc() string {

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

@@ -18,7 +18,7 @@ func TestContainerStatsContext(t *testing.T) {
 		expHeader string
 		expHeader string
 		call      func() 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}, "5.50%", cpuPercHeader, ctx.CPUPerc},
 		{StatsEntry{CPUPercentage: 5.5, IsInvalid: true}, "--", 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},
 		{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 {
 	for _, te := range tt {
 		stats := []StatsEntry{
 		stats := []StatsEntry{
 			{
 			{
-				Name:             "container1",
+				Container:        "container1",
 				CPUPercentage:    20,
 				CPUPercentage:    20,
 				Memory:           20,
 				Memory:           20,
 				MemoryLimit:      20,
 				MemoryLimit:      20,
@@ -96,7 +96,7 @@ container2  --
 				OSType:           "linux",
 				OSType:           "linux",
 			},
 			},
 			{
 			{
-				Name:             "container2",
+				Container:        "container2",
 				CPUPercentage:    30,
 				CPUPercentage:    30,
 				Memory:           30,
 				Memory:           30,
 				MemoryLimit:      30,
 				MemoryLimit:      30,
@@ -150,7 +150,7 @@ container2  --  --
 	for _, te := range tt {
 	for _, te := range tt {
 		stats := []StatsEntry{
 		stats := []StatsEntry{
 			{
 			{
-				Name:             "container1",
+				Container:        "container1",
 				CPUPercentage:    20,
 				CPUPercentage:    20,
 				Memory:           20,
 				Memory:           20,
 				MemoryLimit:      20,
 				MemoryLimit:      20,
@@ -164,7 +164,7 @@ container2  --  --
 				OSType:           "windows",
 				OSType:           "windows",
 			},
 			},
 			{
 			{
-				Name:             "container2",
+				Container:        "container2",
 				CPUPercentage:    30,
 				CPUPercentage:    30,
 				Memory:           30,
 				Memory:           30,
 				MemoryLimit:      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
 	var preRead time.Time
 	getStatJSON := func(v interface{}) *types.StatsJSON {
 	getStatJSON := func(v interface{}) *types.StatsJSON {
 		ss := v.(types.StatsJSON)
 		ss := v.(types.StatsJSON)
+		ss.Name = container.Name
+		ss.ID = container.ID
 		ss.PreCPUStats = preCPUStats
 		ss.PreCPUStats = preCPUStats
 		ss.PreRead = preRead
 		ss.PreRead = preRead
 		preCPUStats = ss.CPUStats
 		preCPUStats = ss.CPUStats