Skip to content

Commit

Permalink
export RunStat
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <[email protected]>
Signed-off-by: Sebastiaan van Stijn <[email protected]>
  • Loading branch information
ndeloof authored and thaJeztah committed Dec 20, 2023
1 parent 1f97a34 commit 649df18
Showing 1 changed file with 41 additions and 32 deletions.
73 changes: 41 additions & 32 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(cmd.Context(), dockerCli, &opts)
options.Containers = args
return RunStats(cmd.Context(), dockerCli, &options)
},
Annotations: map[string]string{
"aliases": "docker container stats, docker stats",
Expand All @@ -48,25 +56,25 @@ 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)
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(ctx context.Context, dockerCli command.Cli, opts *statsOptions) error {
showAll := len(opts.containers) == 0
func RunStats(ctx context.Context, dockerCli command.Cli, options *StatsOptions) error {
showAll := len(options.Containers) == 0
closeChan := make(chan error)

// 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 @@ -108,18 +116,19 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
// getContainerList simulates creation event for all previously existing
// containers (only used when calling `docker stats` without arguments).
getContainerList := func() {
options := container.ListOptions{
All: opts.all,
listOptions := container.ListOptions{
All: options.All,
Filters: options.Filter.Value(),
}
cs, err := dockerCli.Client().ContainerList(ctx, options)
cs, err := dockerCli.Client().ContainerList(ctx, listOptions)
if err != nil {
closeChan <- err
}
for _, ctr := range cs {
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 @@ -132,11 +141,11 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
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 @@ -145,12 +154,12 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
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 @@ -171,11 +180,11 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
} 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 @@ -198,7 +207,7 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
}
}

format := opts.format
format := options.Format
if len(format) == 0 {
if len(dockerCli.ConfigFile().StatsFormat) > 0 {
format = dockerCli.ConfigFile().StatsFormat
Expand All @@ -211,7 +220,7 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
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 @@ -228,13 +237,13 @@ func runStats(ctx context.Context, dockerCli command.Cli, opts *statsOptions) er
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

0 comments on commit 649df18

Please sign in to comment.