Skip to content

Commit

Permalink
export RunStat and introduce filter flag
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <[email protected]>
  • Loading branch information
ndeloof committed Nov 30, 2023
1 parent c1455b6 commit c68fa60
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 30 deletions.
69 changes: 39 additions & 30 deletions cli/command/container/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,41 @@ import (
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/formatter"
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

type statsOptions struct {
all bool
noStream bool
noTrunc bool
format string
containers []string
// StatsOptions defines options for the `stats` command
type StatsOptions struct {
All bool
NoStream bool
NoTrunc bool
Format string
Containers []string
Filter opts.FilterOpt
}

func NewStatsOptions() StatsOptions {
return StatsOptions{
Filter: opts.NewFilterOpt(),
}
}

// NewStatsCommand creates a new cobra.Command for `docker stats`
func NewStatsCommand(dockerCli command.Cli) *cobra.Command {
var opts statsOptions
options := NewStatsOptions()

cmd := &cobra.Command{
Use: "stats [OPTIONS] [CONTAINER...]",
Short: "Display a live stream of container(s) resource usage statistics",
Args: cli.RequiresMinArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
opts.containers = args
return runStats(dockerCli, &opts)
options.Containers = args
return RunStats(dockerCli, &options)
},
Annotations: map[string]string{
"aliases": "docker container stats, docker stats",
Expand All @@ -48,27 +56,28 @@ func NewStatsCommand(dockerCli command.Cli) *cobra.Command {
}

flags := cmd.Flags()
flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)")
flags.BoolVar(&opts.noStream, "no-stream", false, "Disable streaming stats and only pull the first result")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output")
flags.StringVar(&opts.format, "format", "", flagsHelper.FormatHelp)
flags.BoolVarP(&options.All, "all", "a", false, "Show all containers (default shows just running)")
flags.BoolVar(&options.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result")
flags.BoolVar(&options.NoTrunc, "no-trunc", false, "Do not truncate output")
flags.StringVar(&options.Format, "format", "", flagsHelper.FormatHelp)
flags.Var(&options.Filter, "filter", `Filter containers based on conditions provided`)
return cmd
}

// runStats displays a live stream of resource usage statistics for one or more containers.
// RunStats displays a live stream of resource usage statistics for one or more containers.
// This shows real-time information on CPU usage, memory usage, and network I/O.
//
//nolint:gocyclo
func runStats(dockerCli command.Cli, opts *statsOptions) error {
showAll := len(opts.containers) == 0
func RunStats(dockerCli command.Cli, options *StatsOptions) error {
showAll := len(options.Containers) == 0
closeChan := make(chan error)

ctx := context.Background()

// monitorContainerEvents watches for container creation and removal (only
// used when calling `docker stats` without arguments).
monitorContainerEvents := func(started chan<- struct{}, c chan events.Message, stopped <-chan struct{}) {
f := filters.NewArgs()
f := options.Filter.Value()
f.Add("type", "container")
options := types.EventsOptions{
Filters: f,
Expand Down Expand Up @@ -112,7 +121,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
// containers (only used when calling `docker stats` without arguments).
getContainerList := func() {
options := container.ListOptions{
All: opts.all,
All: options.All,
}
cs, err := dockerCli.Client().ContainerList(ctx, options)
if err != nil {
Expand All @@ -122,7 +131,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
s := NewStats(ctr.ID[:12])
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !options.NoStream, waitFirst)
}
}
}
Expand All @@ -135,11 +144,11 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
started := make(chan struct{})
eh := command.InitEventHandler()
eh.Handle(events.ActionCreate, func(e events.Message) {
if opts.all {
if options.All {
s := NewStats(e.Actor.ID[:12])
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !options.NoStream, waitFirst)
}
}
})
Expand All @@ -148,12 +157,12 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
s := NewStats(e.Actor.ID[:12])
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !options.NoStream, waitFirst)
}
})

eh.Handle(events.ActionDie, func(e events.Message) {
if !opts.all {
if !options.All {
cStats.remove(e.Actor.ID[:12])
}
})
Expand All @@ -174,11 +183,11 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
} else {
// Artificially send creation events for the containers we were asked to
// monitor (same code path than we use when monitoring all containers).
for _, name := range opts.containers {
for _, name := range options.Containers {
s := NewStats(name)
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !options.NoStream, waitFirst)
}
}

Expand All @@ -201,7 +210,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
}
}

format := opts.format
format := options.Format
if len(format) == 0 {
if len(dockerCli.ConfigFile().StatsFormat) > 0 {
format = dockerCli.ConfigFile().StatsFormat
Expand All @@ -214,7 +223,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
Format: NewStatsFormat(format, daemonOSType),
}
cleanScreen := func() {
if !opts.noStream {
if !options.NoStream {
fmt.Fprint(dockerCli.Out(), "\033[2J")
fmt.Fprint(dockerCli.Out(), "\033[H")
}
Expand All @@ -231,13 +240,13 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
ccstats = append(ccstats, c.GetStatistics())
}
cStats.mu.RUnlock()
if err = statsFormatWrite(statsCtx, ccstats, daemonOSType, !opts.noTrunc); err != nil {
if err = statsFormatWrite(statsCtx, ccstats, daemonOSType, !options.NoTrunc); err != nil {
break
}
if len(cStats.cs) == 0 && !showAll {
break
}
if opts.noStream {
if options.NoStream {
break
}
select {
Expand Down
1 change: 1 addition & 0 deletions docs/reference/commandline/container_stats.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Display a live stream of container(s) resource usage statistics
| Name | Type | Default | Description |
|:--------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-a`, `--all` | | | Show all containers (default shows just running) |
| `--filter` | `filter` | | Filter containers based on conditions provided |
| `--format` | `string` | | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-stream` | | | Disable streaming stats and only pull the first result |
| `--no-trunc` | | | Do not truncate output |
Expand Down
1 change: 1 addition & 0 deletions docs/reference/commandline/stats.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Display a live stream of container(s) resource usage statistics
| Name | Type | Default | Description |
|:----------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-a`, `--all` | | | Show all containers (default shows just running) |
| `--filter` | `filter` | | Filter containers based on conditions provided |
| [`--format`](#format) | `string` | | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-stream` | | | Disable streaming stats and only pull the first result |
| `--no-trunc` | | | Do not truncate output |
Expand Down

0 comments on commit c68fa60

Please sign in to comment.