From 0f6955c30e26b5d8bad4eb2360993e7e3cf708d6 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 15 Jan 2020 12:22:56 +0100 Subject: v2: stats: fix errors Also add some comments. Signed-off-by: Valentin Rothberg --- pkg/api/handlers/generic/containers_stats.go | 56 +++++++++++++++++----------- pkg/api/handlers/utils/handler.go | 1 + 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go index eb9cfca4a..b8021378b 100644 --- a/pkg/api/handlers/generic/containers_stats.go +++ b/pkg/api/handlers/generic/containers_stats.go @@ -43,6 +43,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { return } + // If the container isn't returning, then let's not bother and return + // immediately. state, err := ctnr.State() if err != nil { utils.InternalServerError(w, err) @@ -56,15 +58,14 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { return } - var preRead time.Time - var preCPUStats docker.CPUStats - stats, err := ctnr.GetContainerStats(&libpod.ContainerStats{}) if err != nil { utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain Container %s stats", name)) return } + var preRead time.Time + var preCPUStats docker.CPUStats if query.Stream { preRead = time.Now() preCPUStats = docker.CPUStats{ @@ -81,16 +82,19 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { time.Sleep(DefaultStatsPeriod) } - cgroupPath, err := ctnr.CGroupPath() - if err != nil { - utils.InternalServerError(w, err) - return - } + // Anonymous function to get the cgroup on demand. + getCgroup := func() *cgroups.CgroupControl { + cgroupPath, err := ctnr.CGroupPath() + if err != nil { + return &cgroups.CgroupControl{} + } - cgroup, err := cgroups.Load(cgroupPath) - if err != nil { - utils.InternalServerError(w, err) - return + cgroup, err := cgroups.Load(cgroupPath) + if err != nil { + return &cgroups.CgroupControl{} + } + + return cgroup } for ok := true; ok; ok = query.Stream { @@ -104,12 +108,13 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { continue } - stats, err := ctnr.GetContainerStats(stats) + cgroup := getCgroup() + cgroupStat, err := cgroup.Stat() if err != nil { - utils.InternalServerError(w, err) - return + cgroupStat = &cgroups.Metrics{} } - cgroupStat, err := cgroup.Stat() + + stats, err := ctnr.GetContainerStats(stats) if err != nil { utils.InternalServerError(w, err) return @@ -120,8 +125,13 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { return } + // FIXME: network inspection does not yet work entirely net := make(map[string]docker.NetworkStats) - net[inspect.NetworkSettings.EndpointID] = docker.NetworkStats{ + networkName := inspect.NetworkSettings.EndpointID + if networkName == "" { + networkName = "network" + } + net[networkName] = docker.NetworkStats{ RxBytes: stats.NetInput, RxPackets: 0, RxErrors: 0, @@ -192,17 +202,21 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { preRead = s.Read bits, err := json.Marshal(s.CPUStats) if err != nil { - logrus.Errorf("unable to marshal cpu stats: %q", err) + logrus.Errorf("Unable to marshal cpu stats: %q", err) } if err := json.Unmarshal(bits, &preCPUStats); err != nil { - logrus.Errorf("unable to unmarshal previous stats: %q", err) + logrus.Errorf("Unable to unmarshal previous stats: %q", err) + } + + // Only sleep when we're streaming. + if query.Stream { + time.Sleep(DefaultStatsPeriod) } - time.Sleep(DefaultStatsPeriod) } } func toBlkioStatEntry(entries []cgroups.BlkIOEntry) []docker.BlkioStatEntry { - results := make([]docker.BlkioStatEntry, 0, len(entries)) + results := make([]docker.BlkioStatEntry, len(entries)) for i, e := range entries { bits, err := json.Marshal(e) if err != nil { diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 8c2110f97..65698bfd3 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -33,6 +33,7 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) { } func WriteJSON(w http.ResponseWriter, code int, value interface{}) { + // FIXME: we don't need to write the header in all/some circumstances. w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) -- cgit v1.2.3-54-g00ecf