1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Allow pulling stats once and disconnecting.

Adds a `stream` query param to the stats API which allows API users to
only collect one stats entry and disconnect instead of keeping the
connection alive to stream more stats.

Also adds a `--no-stream` flag to `docker stats` which does the same

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2015-02-13 11:45:04 -05:00
parent aebeefa886
commit f3023a93d1
11 changed files with 83 additions and 10 deletions

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"net/url"
"sort"
"strings"
"sync"
@ -27,8 +28,14 @@ type containerStats struct {
err error
}
func (s *containerStats) Collect(cli *DockerCli) {
stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats", nil, nil)
func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
v := url.Values{}
if streamStats {
v.Set("stream", "1")
} else {
v.Set("stream", "0")
}
stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats?"+v.Encode(), nil, nil)
if err != nil {
s.err = err
return
@ -67,6 +74,9 @@ func (s *containerStats) Collect(cli *DockerCli) {
previousCPU = v.CpuStats.CpuUsage.TotalUsage
previousSystem = v.CpuStats.SystemUsage
u <- nil
if !streamStats {
return
}
}
}()
for {
@ -87,6 +97,9 @@ func (s *containerStats) Collect(cli *DockerCli) {
return
}
}
if !streamStats {
return
}
}
}
@ -112,6 +125,7 @@ func (s *containerStats) Display(w io.Writer) error {
// Usage: docker stats CONTAINER [CONTAINER...]
func (cli *DockerCli) CmdStats(args ...string) error {
cmd := cli.Subcmd("stats", "CONTAINER [CONTAINER...]", "Display a live stream of one or more containers' resource usage statistics", true)
noStream := cmd.Bool([]string{"-no-stream"}, false, "Disable streaming stats and only pull the first result")
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
@ -122,14 +136,16 @@ func (cli *DockerCli) CmdStats(args ...string) error {
w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
)
printHeader := func() {
io.WriteString(cli.out, "\033[2J")
io.WriteString(cli.out, "\033[H")
if !*noStream {
fmt.Fprint(cli.out, "\033[2J")
fmt.Fprint(cli.out, "\033[H")
}
io.WriteString(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O\n")
}
for _, n := range names {
s := &containerStats{Name: n}
cStats = append(cStats, s)
go s.Collect(cli)
go s.Collect(cli, !*noStream)
}
// do a quick pause so that any failed connections for containers that do not exist are able to be
// evicted before we display the initial or default values.
@ -149,7 +165,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
printHeader()
toRemove := []int{}
for i, s := range cStats {
if err := s.Display(w); err != nil {
if err := s.Display(w); err != nil && !*noStream {
toRemove = append(toRemove, i)
}
}
@ -161,6 +177,9 @@ func (cli *DockerCli) CmdStats(args ...string) error {
return nil
}
w.Flush()
if *noStream {
break
}
}
return nil
}

View file

@ -611,7 +611,7 @@ func (s *Server) getContainersStats(eng *engine.Engine, version version.Version,
return fmt.Errorf("Missing parameter")
}
return s.daemon.ContainerStats(vars["name"], utils.NewWriteFlusher(w))
return s.daemon.ContainerStats(vars["name"], boolValue(r, "stream"), utils.NewWriteFlusher(w))
}
func (s *Server) getContainersLogs(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {

View file

@ -1003,7 +1003,7 @@ _docker_start() {
_docker_stats() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--no-stream --help" -- "$cur" ) )
;;
*)
__docker_containers_running

View file

@ -16,7 +16,7 @@
function __fish_docker_no_subcommand --description 'Test if docker has yet to be given the subcommand'
for i in (commandline -opc)
if contains -- $i attach build commit cp create diff events exec export history images import info inspect kill load login logout logs pause port ps pull push rename restart rm rmi run save search start stop tag top unpause version wait
if contains -- $i attach build commit cp create diff events exec export history images import info inspect kill load login logout logs pause port ps pull push rename restart rm rmi run save search start stop tag top unpause version wait stats
return 1
end
end
@ -361,6 +361,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from start' -a '(__fish_prin
# stats
complete -c docker -f -n '__fish_docker_no_subcommand' -a stats -d "Display a live stream of one or more containers' resource usage statistics"
complete -c docker -A -f -n '__fish_seen_subcommand_from stats' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from stats' -l no-stream -d 'Disable streaming stats and only pull the first result'
complete -c docker -A -f -n '__fish_seen_subcommand_from stats' -a '(__fish_print_docker_containers running)' -d "Container"
# stop

View file

@ -326,6 +326,7 @@ __docker_subcommand () {
;;
(stats)
_arguments \
'--no-stream[Disable streaming stats and only pull the first result]' \
'*:containers:__docker_runningcontainers'
;;
(rm)

View file

@ -10,7 +10,7 @@ import (
"github.com/docker/libcontainer/cgroups"
)
func (daemon *Daemon) ContainerStats(name string, out io.Writer) error {
func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) error {
updates, err := daemon.SubscribeToContainerStats(name)
if err != nil {
return err
@ -27,6 +27,9 @@ func (daemon *Daemon) ContainerStats(name string, out io.Writer) error {
daemon.UnsubscribeToContainerStats(name, updates)
return err
}
if !stream {
break
}
}
return nil
}

View file

@ -17,6 +17,9 @@ Display a live stream of one or more containers' resource usage statistics
**--help**
Print usage statement
**--no-stream**="false"
Disable streaming stats and only pull the first result
# EXAMPLES
Run **docker stats** with multiple containers.

View file

@ -46,6 +46,11 @@ You can still call an old version of the API using
### What's new
`GET /containers/(id)/stats`
**New!**
You can now supply a `stream` bool to get only one set of stats and
disconnect
## v1.18

View file

@ -644,6 +644,10 @@ This endpoint returns a live stream of a container's resource usage statistics.
}
}
Query Parameters:
- **stream** 1/True/true or 0/False/false, pull stats once then disconnect. Default true
Status Codes:
- **200** no error

View file

@ -2377,6 +2377,7 @@ more details on finding shared images from the command line.
Display a live stream of one or more containers' resource usage statistics
--help=false Print usage
--no-stream=false Disable streaming stats and only pull the first result
Running `docker stats` on multiple containers

View file

@ -0,0 +1,36 @@
package main
import (
"os/exec"
"strings"
"time"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliStatsNoStream(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "top"))
if err != nil {
c.Fatalf("Error on container creation: %v, output: %s", err, out)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
c.Fatalf("error waiting for container to start: %v", err)
}
statsCmd := exec.Command(dockerBinary, "stats", "--no-stream", id)
chErr := make(chan error)
go func() {
chErr <- statsCmd.Run()
}()
select {
case err := <-chErr:
if err != nil {
c.Fatalf("Error running stats: %v", err)
}
case <-time.After(2 * time.Second):
statsCmd.Process.Kill()
c.Fatalf("stats did not return immediately when not streaming")
}
}