From eb405d2b73f90c2bf311110f8f39c0c415837297 Mon Sep 17 00:00:00 2001 From: Lei Jitang Date: Thu, 7 Apr 2016 22:09:07 -0400 Subject: [PATCH] Fix docker stats missing memory limit Signed-off-by: Lei Jitang (cherry picked from commit a0a6d031d76c1bf9d5581a8310b8a2d1df4b7b82) --- daemon/daemon_unix.go | 5 +++++ daemon/stats_collector_unix.go | 7 ++++++ integration-cli/docker_api_stats_test.go | 28 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index a152fd0e95..9a4ab32296 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -1092,6 +1092,11 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) { MaxUsage: mem.MaxUsage, Stats: cgs.MemoryStats.Stats, Failcnt: mem.Failcnt, + Limit: mem.Limit, + } + // if the container does not set memory limit, use the machineMemory + if mem.Limit > daemon.statsCollector.machineMemory && daemon.statsCollector.machineMemory > 0 { + s.MemoryStats.Limit = daemon.statsCollector.machineMemory } if cgs.PidsStats != nil { s.PidsStats = types.PidsStats{ diff --git a/daemon/stats_collector_unix.go b/daemon/stats_collector_unix.go index 5010281498..fb1931dfb8 100644 --- a/daemon/stats_collector_unix.go +++ b/daemon/stats_collector_unix.go @@ -14,6 +14,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/container" "github.com/docker/docker/pkg/pubsub" + sysinfo "github.com/docker/docker/pkg/system" "github.com/docker/engine-api/types" "github.com/opencontainers/runc/libcontainer/system" ) @@ -35,6 +36,11 @@ func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector clockTicksPerSecond: uint64(system.GetClockTicks()), bufReader: bufio.NewReaderSize(nil, 128), } + meminfo, err := sysinfo.ReadMemInfo() + if err == nil && meminfo.MemTotal > 0 { + s.machineMemory = uint64(meminfo.MemTotal) + } + go s.run() return s } @@ -47,6 +53,7 @@ type statsCollector struct { clockTicksPerSecond uint64 publishers map[*container.Container]*pubsub.Publisher bufReader *bufio.Reader + machineMemory uint64 } // collect registers the container with the collector and adds it to diff --git a/integration-cli/docker_api_stats_test.go b/integration-cli/docker_api_stats_test.go index 10c9fd5b20..7c3f8d3916 100644 --- a/integration-cli/docker_api_stats_test.go +++ b/integration-cli/docker_api_stats_test.go @@ -227,3 +227,31 @@ func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) { c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusNotFound) } + +func (s *DockerSuite) TestApiStatsContainerGetMemoryLimit(c *check.C) { + testRequires(c, DaemonIsLinux) + + resp, body, err := sockRequestRaw("GET", "/info", nil, "application/json") + c.Assert(err, checker.IsNil) + c.Assert(resp.StatusCode, checker.Equals, http.StatusOK) + var info types.Info + err = json.NewDecoder(body).Decode(&info) + c.Assert(err, checker.IsNil) + body.Close() + + // don't set a memory limit, the memory limit should be system memory + conName := "foo" + dockerCmd(c, "run", "-d", "--name", conName, "busybox", "top") + c.Assert(waitRun(conName), checker.IsNil) + + resp, body, err = sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", conName), nil, "") + c.Assert(err, checker.IsNil) + c.Assert(resp.StatusCode, checker.Equals, http.StatusOK) + c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json") + + var v *types.Stats + err = json.NewDecoder(body).Decode(&v) + c.Assert(err, checker.IsNil) + body.Close() + c.Assert(fmt.Sprintf("%d", v.MemoryStats.Limit), checker.Equals, fmt.Sprintf("%d", info.MemTotal)) +}