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>
This commit is contained in:
Vincent Demeester 2016-11-03 07:20:46 +01:00
parent 1f4137857f
commit ef915fd036
No known key found for this signature in database
GPG Key ID: 083CC6FD6EB699A3
5 changed files with 33 additions and 13 deletions

View File

@ -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"`
}

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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