summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/api/handlers/generic/containers_stats.go76
-rw-r--r--pkg/api/handlers/libpod/containers.go4
-rw-r--r--pkg/api/handlers/utils/handler.go1
-rw-r--r--pkg/api/server/register_containers.go25
4 files changed, 71 insertions, 35 deletions
diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go
index 0c4efc1df..26c8efa15 100644
--- a/pkg/api/handlers/generic/containers_stats.go
+++ b/pkg/api/handlers/generic/containers_stats.go
@@ -43,28 +43,26 @@ 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)
return
}
if state != define.ContainerStateRunning && !query.Stream {
- utils.WriteJSON(w, http.StatusOK, &handlers.Stats{StatsJSON: docker.StatsJSON{
- Name: ctnr.Name(),
- ID: ctnr.ID(),
- }})
+ utils.InternalServerError(w, define.ErrCtrStateInvalid)
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{
@@ -78,25 +76,44 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
OnlineCPUs: 0,
ThrottlingData: docker.ThrottlingData{},
}
- time.Sleep(DefaultStatsPeriod)
}
- cgroupPath, _ := ctnr.CGroupPath()
- cgroup, _ := cgroups.Load(cgroupPath)
-
for ok := true; ok; ok = query.Stream {
- state, _ := ctnr.State()
- if state != define.ContainerStateRunning {
- time.Sleep(10 * time.Second)
- continue
+ // Container stats
+ stats, err := ctnr.GetContainerStats(stats)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ inspect, err := ctnr.Inspect(false)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ // Cgroup stats
+ cgroupPath, err := ctnr.CGroupPath()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ cgroup, err := cgroups.Load(cgroupPath)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ cgroupStat, err := cgroup.Stat()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
}
- stats, _ := ctnr.GetContainerStats(stats)
- cgroupStat, _ := cgroup.Stat()
- inspect, _ := ctnr.Inspect(false)
-
+ // 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,
@@ -127,13 +144,6 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
IoTimeRecursive: nil,
SectorsRecursive: nil,
},
- NumProcs: 0,
- StorageStats: docker.StorageStats{
- ReadCountNormalized: 0,
- ReadSizeBytes: 0,
- WriteCountNormalized: 0,
- WriteSizeBytes: 0,
- },
CPUStats: docker.CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: cgroupStat.CPU.Usage.Total,
@@ -174,17 +184,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/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index bfb028b1b..ceb7460da 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -143,9 +143,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
// timestamps
// tail string
}
-func StatsContainer(w http.ResponseWriter, r *http.Request) {
- //stream
-}
+
func CreateContainer(w http.ResponseWriter, r *http.Request) {
}
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)
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 711aecc84..95b986170 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -629,7 +629,30 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// '500':
// "$ref": "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost)
- r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, libpod.StatsContainer)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/containers/{nameOrID}/stats containers statsContainer
+ // ---
+ // summary: Get stats for a container
+ // description: This returns a live stream of a container’s resource usage statistics.
+ // parameters:
+ // - in: path
+ // name: nameOrID
+ // required: true
+ // description: the name or ID of the container
+ // - in: query
+ // name: stream
+ // type: bool
+ // default: true
+ // description: Stream the output
+ // produces:
+ // - application/json
+ // responses:
+ // '200':
+ // description: no error
+ // '404':
+ // "$ref": "#/responses/NoSuchContainer"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet)
r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{nameOrID}/unpause containers libpodUnpauseContainer
// ---