mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
cgroup2: implement docker stats
The following fields are unsupported: * BlkioStats: all fields other than IoServiceBytesRecursive * CPUStats: CPUUsage.PercpuUsage * MemoryStats: MaxUsage and Failcnt Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
parent
bd81cf2859
commit
3802830989
6 changed files with 3847 additions and 4 deletions
|
@ -5564,6 +5564,12 @@ paths:
|
|||
If either `precpu_stats.online_cpus` or `cpu_stats.online_cpus` is
|
||||
nil then for compatibility with older daemons the length of the
|
||||
corresponding `cpu_usage.percpu_usage` array should be used.
|
||||
|
||||
On a cgroup v2 host, the following fields are not set
|
||||
* `blkio_stats`: all fields other than `io_service_bytes_recursive`
|
||||
* `cpu_stats`: `cpu_usage.percpu_usage`
|
||||
* `memory_stats`: `max_usage` and `failcnt`
|
||||
Also, `memory_stats.stats` fields are incompatible with cgroup v1.
|
||||
operationId: "ContainerStats"
|
||||
produces: ["application/json"]
|
||||
responses:
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"time"
|
||||
|
||||
statsV1 "github.com/containerd/cgroups/stats/v1"
|
||||
statsV2 "github.com/containerd/cgroups/v2/stats"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/blkiodev"
|
||||
pblkiodev "github.com/docker/docker/api/types/blkiodev"
|
||||
|
@ -1446,6 +1447,17 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
|
|||
s := &types.StatsJSON{}
|
||||
s.Read = cs.Read
|
||||
stats := cs.Metrics
|
||||
switch t := stats.(type) {
|
||||
case *statsV1.Metrics:
|
||||
return daemon.statsV1(s, t)
|
||||
case *statsV2.Metrics:
|
||||
return daemon.statsV2(s, t)
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected type of metrics %+v", t)
|
||||
}
|
||||
}
|
||||
|
||||
func (daemon *Daemon) statsV1(s *types.StatsJSON, stats *statsV1.Metrics) (*types.StatsJSON, error) {
|
||||
if stats.Blkio != nil {
|
||||
s.BlkioStats = types.BlkioStats{
|
||||
IoServiceBytesRecursive: copyBlkioEntry(stats.Blkio.IoServiceBytesRecursive),
|
||||
|
@ -1539,6 +1551,104 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) statsV2(s *types.StatsJSON, stats *statsV2.Metrics) (*types.StatsJSON, error) {
|
||||
if stats.Io != nil {
|
||||
var isbr []types.BlkioStatEntry
|
||||
for _, re := range stats.Io.Usage {
|
||||
isbr = append(isbr,
|
||||
types.BlkioStatEntry{
|
||||
Major: re.Major,
|
||||
Minor: re.Minor,
|
||||
Op: "read",
|
||||
Value: re.Rbytes,
|
||||
},
|
||||
types.BlkioStatEntry{
|
||||
Major: re.Major,
|
||||
Minor: re.Minor,
|
||||
Op: "write",
|
||||
Value: re.Wbytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
s.BlkioStats = types.BlkioStats{
|
||||
IoServiceBytesRecursive: isbr,
|
||||
// Other fields are unsupported
|
||||
}
|
||||
}
|
||||
|
||||
if stats.CPU != nil {
|
||||
s.CPUStats = types.CPUStats{
|
||||
CPUUsage: types.CPUUsage{
|
||||
TotalUsage: stats.CPU.UsageUsec * 1000,
|
||||
// PercpuUsage is not supported
|
||||
UsageInKernelmode: stats.CPU.SystemUsec * 1000,
|
||||
UsageInUsermode: stats.CPU.UserUsec * 1000,
|
||||
},
|
||||
ThrottlingData: types.ThrottlingData{
|
||||
Periods: stats.CPU.NrPeriods,
|
||||
ThrottledPeriods: stats.CPU.NrThrottled,
|
||||
ThrottledTime: stats.CPU.ThrottledUsec * 1000,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if stats.Memory != nil {
|
||||
raw := make(map[string]uint64)
|
||||
raw["anon"] = stats.Memory.Anon
|
||||
raw["file"] = stats.Memory.File
|
||||
raw["kernel_stack"] = stats.Memory.KernelStack
|
||||
raw["slab"] = stats.Memory.Slab
|
||||
raw["sock"] = stats.Memory.Sock
|
||||
raw["shmem"] = stats.Memory.Shmem
|
||||
raw["file_mapped"] = stats.Memory.FileMapped
|
||||
raw["file_dirty"] = stats.Memory.FileDirty
|
||||
raw["file_writeback"] = stats.Memory.FileWriteback
|
||||
raw["anon_thp"] = stats.Memory.AnonThp
|
||||
raw["inactive_anon"] = stats.Memory.InactiveAnon
|
||||
raw["active_anon"] = stats.Memory.ActiveAnon
|
||||
raw["inactive_file"] = stats.Memory.InactiveFile
|
||||
raw["active_file"] = stats.Memory.ActiveFile
|
||||
raw["unevictable"] = stats.Memory.Unevictable
|
||||
raw["slab_reclaimable"] = stats.Memory.SlabReclaimable
|
||||
raw["slab_unreclaimable"] = stats.Memory.SlabUnreclaimable
|
||||
raw["pgfault"] = stats.Memory.Pgfault
|
||||
raw["pgmajfault"] = stats.Memory.Pgmajfault
|
||||
raw["workingset_refault"] = stats.Memory.WorkingsetRefault
|
||||
raw["workingset_activate"] = stats.Memory.WorkingsetActivate
|
||||
raw["workingset_nodereclaim"] = stats.Memory.WorkingsetNodereclaim
|
||||
raw["pgrefill"] = stats.Memory.Pgrefill
|
||||
raw["pgscan"] = stats.Memory.Pgscan
|
||||
raw["pgsteal"] = stats.Memory.Pgsteal
|
||||
raw["pgactivate"] = stats.Memory.Pgactivate
|
||||
raw["pgdeactivate"] = stats.Memory.Pgdeactivate
|
||||
raw["pglazyfree"] = stats.Memory.Pglazyfree
|
||||
raw["pglazyfreed"] = stats.Memory.Pglazyfreed
|
||||
raw["thp_fault_alloc"] = stats.Memory.ThpFaultAlloc
|
||||
raw["thp_collapse_alloc"] = stats.Memory.ThpCollapseAlloc
|
||||
s.MemoryStats = types.MemoryStats{
|
||||
// Stats is not compatible with v1
|
||||
Stats: raw,
|
||||
Usage: stats.Memory.Usage,
|
||||
// MaxUsage is not supported
|
||||
Limit: stats.Memory.UsageLimit,
|
||||
// TODO: Failcnt
|
||||
}
|
||||
// if the container does not set memory limit, use the machineMemory
|
||||
if s.MemoryStats.Limit > daemon.machineMemory && daemon.machineMemory > 0 {
|
||||
s.MemoryStats.Limit = daemon.machineMemory
|
||||
}
|
||||
}
|
||||
|
||||
if stats.Pids != nil {
|
||||
s.PidsStats = types.PidsStats{
|
||||
Current: stats.Pids.Current,
|
||||
Limit: stats.Pids.Limit,
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// setDefaultIsolation determines the default isolation mode for the
|
||||
// daemon to run in. This is only applicable on Windows
|
||||
func (daemon *Daemon) setDefaultIsolation() error {
|
||||
|
|
|
@ -3,7 +3,6 @@ package types // import "github.com/docker/docker/libcontainerd/types"
|
|||
import (
|
||||
"time"
|
||||
|
||||
statsV1 "github.com/containerd/cgroups/stats/v1"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
|
@ -12,14 +11,17 @@ type Summary struct{}
|
|||
|
||||
// Stats holds metrics properties as returned by containerd
|
||||
type Stats struct {
|
||||
Read time.Time
|
||||
Metrics *statsV1.Metrics
|
||||
Read time.Time
|
||||
// Metrics is expected to be either one of:
|
||||
// * github.com/containerd/cgroups/stats/v1.Metrics
|
||||
// * github.com/containerd/cgroups/stats/v2.Metrics
|
||||
Metrics interface{}
|
||||
}
|
||||
|
||||
// InterfaceToStats returns a stats object from the platform-specific interface.
|
||||
func InterfaceToStats(read time.Time, v interface{}) *Stats {
|
||||
return &Stats{
|
||||
Metrics: v.(*statsV1.Metrics),
|
||||
Metrics: v,
|
||||
Read: read,
|
||||
}
|
||||
}
|
||||
|
|
17
vendor/github.com/containerd/cgroups/v2/stats/doc.go
generated
vendored
Normal file
17
vendor/github.com/containerd/cgroups/v2/stats/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package stats
|
3612
vendor/github.com/containerd/cgroups/v2/stats/metrics.pb.go
generated
vendored
Normal file
3612
vendor/github.com/containerd/cgroups/v2/stats/metrics.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
96
vendor/github.com/containerd/cgroups/v2/stats/metrics.proto
generated
vendored
Normal file
96
vendor/github.com/containerd/cgroups/v2/stats/metrics.proto
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package io.containerd.cgroups.v2;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
message Metrics {
|
||||
PidsStat pids = 1;
|
||||
CPUStat cpu = 2 [(gogoproto.customname) = "CPU"];
|
||||
MemoryStat memory = 4;
|
||||
RdmaStat rdma = 5;
|
||||
IOStat io = 6;
|
||||
repeated HugeTlbStat hugetlb = 7;
|
||||
}
|
||||
|
||||
message PidsStat {
|
||||
uint64 current = 1;
|
||||
uint64 limit = 2;
|
||||
}
|
||||
|
||||
message CPUStat {
|
||||
uint64 usage_usec = 1;
|
||||
uint64 user_usec = 2;
|
||||
uint64 system_usec = 3;
|
||||
uint64 nr_periods = 4;
|
||||
uint64 nr_throttled = 5;
|
||||
uint64 throttled_usec = 6;
|
||||
}
|
||||
|
||||
message MemoryStat {
|
||||
uint64 anon = 1;
|
||||
uint64 file = 2;
|
||||
uint64 kernel_stack = 3;
|
||||
uint64 slab = 4;
|
||||
uint64 sock = 5;
|
||||
uint64 shmem = 6;
|
||||
uint64 file_mapped = 7;
|
||||
uint64 file_dirty = 8;
|
||||
uint64 file_writeback = 9;
|
||||
uint64 anon_thp = 10;
|
||||
uint64 inactive_anon = 11;
|
||||
uint64 active_anon = 12;
|
||||
uint64 inactive_file = 13;
|
||||
uint64 active_file = 14;
|
||||
uint64 unevictable = 15;
|
||||
uint64 slab_reclaimable = 16;
|
||||
uint64 slab_unreclaimable = 17;
|
||||
uint64 pgfault = 18;
|
||||
uint64 pgmajfault = 19;
|
||||
uint64 workingset_refault = 20;
|
||||
uint64 workingset_activate = 21;
|
||||
uint64 workingset_nodereclaim = 22;
|
||||
uint64 pgrefill = 23;
|
||||
uint64 pgscan = 24;
|
||||
uint64 pgsteal = 25;
|
||||
uint64 pgactivate = 26;
|
||||
uint64 pgdeactivate = 27;
|
||||
uint64 pglazyfree = 28;
|
||||
uint64 pglazyfreed = 29;
|
||||
uint64 thp_fault_alloc = 30;
|
||||
uint64 thp_collapse_alloc = 31;
|
||||
uint64 usage = 32;
|
||||
uint64 usage_limit = 33;
|
||||
uint64 swap_usage = 34;
|
||||
uint64 swap_limit = 35;
|
||||
}
|
||||
|
||||
message RdmaStat {
|
||||
repeated RdmaEntry current = 1;
|
||||
repeated RdmaEntry limit = 2;
|
||||
}
|
||||
|
||||
message RdmaEntry {
|
||||
string device = 1;
|
||||
uint32 hca_handles = 2;
|
||||
uint32 hca_objects = 3;
|
||||
}
|
||||
|
||||
message IOStat {
|
||||
repeated IOEntry usage = 1;
|
||||
}
|
||||
|
||||
message IOEntry {
|
||||
uint64 major = 1;
|
||||
uint64 minor = 2;
|
||||
uint64 rbytes = 3;
|
||||
uint64 wbytes = 4;
|
||||
uint64 rios = 5;
|
||||
uint64 wios = 6;
|
||||
}
|
||||
|
||||
message HugeTlbStat {
|
||||
uint64 current = 1;
|
||||
uint64 max = 2;
|
||||
string pagesize = 3;
|
||||
}
|
Loading…
Reference in a new issue