Files
docker-cli/components/engine/integration-cli/docker_api_stats_test.go
Hu Keping c71aa53e3d Refactor the statistics of network in docker stats
For now docker stats will sum the rxbytes, txbytes, etc. of all
the interfaces.

It is OK for the output of CLI `docker stats` but not good for
the API response, especially when the container is in sereval
subnets.

It's better to leave these origianl data to user.

Signed-off-by: Hu Keping <hukeping@huawei.com>
Upstream-commit: d3379946ec96fb6163cb8c4517d7d5a067045801
Component: engine
2015-09-15 15:40:34 +08:00

136 lines
4.1 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os/exec"
"runtime"
"strconv"
"strings"
"time"
"github.com/docker/docker/api/types"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliStatsNoStreamGetCpu(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true;do echo 'Hello'; usleep 100000; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
c.Assert(err, check.IsNil)
c.Assert(resp.ContentLength > 0, check.Equals, true, check.Commentf("should not use chunked encoding"))
c.Assert(resp.Header.Get("Content-Type"), check.Equals, "application/json")
var v *types.Stats
err = json.NewDecoder(body).Decode(&v)
c.Assert(err, check.IsNil)
body.Close()
var cpuPercent = 0.0
cpuDelta := float64(v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage)
systemDelta := float64(v.CPUStats.SystemUsage - v.PreCPUStats.SystemUsage)
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
if cpuPercent == 0 {
c.Fatalf("docker stats with no-stream get cpu usage failed: was %v", cpuPercent)
}
}
func (s *DockerSuite) TestStoppedContainerStatsGoroutines(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo 1")
id := strings.TrimSpace(out)
getGoRoutines := func() int {
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/info"), nil, "")
c.Assert(err, check.IsNil)
info := types.Info{}
err = json.NewDecoder(body).Decode(&info)
c.Assert(err, check.IsNil)
body.Close()
return info.NGoroutines
}
// When the HTTP connection is closed, the number of goroutines should not increase.
routines := getGoRoutines()
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats", id), nil, "")
c.Assert(err, check.IsNil)
body.Close()
t := time.After(30 * time.Second)
for {
select {
case <-t:
c.Assert(getGoRoutines() <= routines, check.Equals, true)
return
default:
if n := getGoRoutines(); n <= routines {
return
}
time.Sleep(200 * time.Millisecond)
}
}
}
func (s *DockerSuite) TestApiNetworkStats(c *check.C) {
testRequires(c, SameHostDaemon)
testRequires(c, DaemonIsLinux)
// Run container for 30 secs
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
// Retrieve the container address
contIP := findContainerIP(c, id)
numPings := 10
var preRxPackets uint64
var preTxPackets uint64
var postRxPackets uint64
var postTxPackets uint64
// Get the container networking stats before and after pinging the container
nwStatsPre := getNetworkStats(c, id)
for _, v := range nwStatsPre {
preRxPackets += v.RxPackets
preTxPackets += v.TxPackets
}
countParam := "-c"
if runtime.GOOS == "windows" {
countParam = "-n" // Ping count parameter is -n on Windows
}
pingout, err := exec.Command("ping", contIP, countParam, strconv.Itoa(numPings)).Output()
pingouts := string(pingout[:])
c.Assert(err, check.IsNil)
nwStatsPost := getNetworkStats(c, id)
for _, v := range nwStatsPost {
postRxPackets += v.RxPackets
postTxPackets += v.TxPackets
}
// Verify the stats contain at least the expected number of packets (account for ARP)
expRxPkts := 1 + preRxPackets + uint64(numPings)
expTxPkts := 1 + preTxPackets + uint64(numPings)
c.Assert(postTxPackets >= expTxPkts, check.Equals, true,
check.Commentf("Reported less TxPackets than expected. Expected >= %d. Found %d. %s", expTxPkts, postTxPackets, pingouts))
c.Assert(postRxPackets >= expRxPkts, check.Equals, true,
check.Commentf("Reported less Txbytes than expected. Expected >= %d. Found %d. %s", expRxPkts, postRxPackets, pingouts))
}
func getNetworkStats(c *check.C, id string) map[string]types.NetworkStats {
var st *types.StatsJSON
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
c.Assert(err, check.IsNil)
err = json.NewDecoder(body).Decode(&st)
c.Assert(err, check.IsNil)
body.Close()
return st.Networks
}