daemon: move code related to stats together

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-04-08 19:00:01 +02:00
parent dd3b71d17c
commit f691b13450
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
4 changed files with 309 additions and 306 deletions

View file

@ -19,10 +19,7 @@ import (
"time"
"github.com/containerd/cgroups/v3"
statsV1 "github.com/containerd/cgroups/v3/cgroup1/stats"
statsV2 "github.com/containerd/cgroups/v3/cgroup2/stats"
"github.com/containerd/containerd/pkg/userns"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/blkiodev"
pblkiodev "github.com/docker/docker/api/types/blkiodev"
containertypes "github.com/docker/docker/api/types/container"
@ -1409,242 +1406,6 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container
return nil
}
func copyBlkioEntry(entries []*statsV1.BlkIOEntry) []types.BlkioStatEntry {
out := make([]types.BlkioStatEntry, len(entries))
for i, re := range entries {
out[i] = types.BlkioStatEntry{
Major: re.Major,
Minor: re.Minor,
Op: re.Op,
Value: re.Value,
}
}
return out
}
func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
c.Lock()
task, err := c.GetRunningTask()
c.Unlock()
if err != nil {
return nil, err
}
cs, err := task.Stats(context.Background())
if err != nil {
if strings.Contains(err.Error(), "container not found") {
return nil, containerNotFound(c.ID)
}
return nil, err
}
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),
IoServicedRecursive: copyBlkioEntry(stats.Blkio.IoServicedRecursive),
IoQueuedRecursive: copyBlkioEntry(stats.Blkio.IoQueuedRecursive),
IoServiceTimeRecursive: copyBlkioEntry(stats.Blkio.IoServiceTimeRecursive),
IoWaitTimeRecursive: copyBlkioEntry(stats.Blkio.IoWaitTimeRecursive),
IoMergedRecursive: copyBlkioEntry(stats.Blkio.IoMergedRecursive),
IoTimeRecursive: copyBlkioEntry(stats.Blkio.IoTimeRecursive),
SectorsRecursive: copyBlkioEntry(stats.Blkio.SectorsRecursive),
}
}
if stats.CPU != nil {
s.CPUStats = types.CPUStats{
CPUUsage: types.CPUUsage{
TotalUsage: stats.CPU.Usage.Total,
PercpuUsage: stats.CPU.Usage.PerCPU,
UsageInKernelmode: stats.CPU.Usage.Kernel,
UsageInUsermode: stats.CPU.Usage.User,
},
ThrottlingData: types.ThrottlingData{
Periods: stats.CPU.Throttling.Periods,
ThrottledPeriods: stats.CPU.Throttling.ThrottledPeriods,
ThrottledTime: stats.CPU.Throttling.ThrottledTime,
},
}
}
if stats.Memory != nil {
raw := map[string]uint64{
"cache": stats.Memory.Cache,
"rss": stats.Memory.RSS,
"rss_huge": stats.Memory.RSSHuge,
"mapped_file": stats.Memory.MappedFile,
"dirty": stats.Memory.Dirty,
"writeback": stats.Memory.Writeback,
"pgpgin": stats.Memory.PgPgIn,
"pgpgout": stats.Memory.PgPgOut,
"pgfault": stats.Memory.PgFault,
"pgmajfault": stats.Memory.PgMajFault,
"inactive_anon": stats.Memory.InactiveAnon,
"active_anon": stats.Memory.ActiveAnon,
"inactive_file": stats.Memory.InactiveFile,
"active_file": stats.Memory.ActiveFile,
"unevictable": stats.Memory.Unevictable,
"hierarchical_memory_limit": stats.Memory.HierarchicalMemoryLimit,
"hierarchical_memsw_limit": stats.Memory.HierarchicalSwapLimit,
"total_cache": stats.Memory.TotalCache,
"total_rss": stats.Memory.TotalRSS,
"total_rss_huge": stats.Memory.TotalRSSHuge,
"total_mapped_file": stats.Memory.TotalMappedFile,
"total_dirty": stats.Memory.TotalDirty,
"total_writeback": stats.Memory.TotalWriteback,
"total_pgpgin": stats.Memory.TotalPgPgIn,
"total_pgpgout": stats.Memory.TotalPgPgOut,
"total_pgfault": stats.Memory.TotalPgFault,
"total_pgmajfault": stats.Memory.TotalPgMajFault,
"total_inactive_anon": stats.Memory.TotalInactiveAnon,
"total_active_anon": stats.Memory.TotalActiveAnon,
"total_inactive_file": stats.Memory.TotalInactiveFile,
"total_active_file": stats.Memory.TotalActiveFile,
"total_unevictable": stats.Memory.TotalUnevictable,
}
if stats.Memory.Usage != nil {
s.MemoryStats = types.MemoryStats{
Stats: raw,
Usage: stats.Memory.Usage.Usage,
MaxUsage: stats.Memory.Usage.Max,
Limit: stats.Memory.Usage.Limit,
Failcnt: stats.Memory.Usage.Failcnt,
}
} else {
s.MemoryStats = types.MemoryStats{
Stats: raw,
}
}
// 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
}
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 {
s.MemoryStats = types.MemoryStats{
// Stats is not compatible with v1
Stats: map[string]uint64{
"anon": stats.Memory.Anon,
"file": stats.Memory.File,
"kernel_stack": stats.Memory.KernelStack,
"slab": stats.Memory.Slab,
"sock": stats.Memory.Sock,
"shmem": stats.Memory.Shmem,
"file_mapped": stats.Memory.FileMapped,
"file_dirty": stats.Memory.FileDirty,
"file_writeback": stats.Memory.FileWriteback,
"anon_thp": stats.Memory.AnonThp,
"inactive_anon": stats.Memory.InactiveAnon,
"active_anon": stats.Memory.ActiveAnon,
"inactive_file": stats.Memory.InactiveFile,
"active_file": stats.Memory.ActiveFile,
"unevictable": stats.Memory.Unevictable,
"slab_reclaimable": stats.Memory.SlabReclaimable,
"slab_unreclaimable": stats.Memory.SlabUnreclaimable,
"pgfault": stats.Memory.Pgfault,
"pgmajfault": stats.Memory.Pgmajfault,
"workingset_refault": stats.Memory.WorkingsetRefault,
"workingset_activate": stats.Memory.WorkingsetActivate,
"workingset_nodereclaim": stats.Memory.WorkingsetNodereclaim,
"pgrefill": stats.Memory.Pgrefill,
"pgscan": stats.Memory.Pgscan,
"pgsteal": stats.Memory.Pgsteal,
"pgactivate": stats.Memory.Pgactivate,
"pgdeactivate": stats.Memory.Pgdeactivate,
"pglazyfree": stats.Memory.Pglazyfree,
"pglazyfreed": stats.Memory.Pglazyfreed,
"thp_fault_alloc": stats.Memory.ThpFaultAlloc,
"thp_collapse_alloc": stats.Memory.ThpCollapseAlloc,
},
Usage: stats.Memory.Usage,
// MaxUsage is not supported
Limit: stats.Memory.UsageLimit,
}
// 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.MemoryEvents != nil {
// Failcnt is set to the "oom" field of the "memory.events" file.
// See https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
s.MemoryStats.Failcnt = stats.MemoryEvents.Oom
}
}
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 {

View file

@ -10,11 +10,9 @@ import (
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/osversion"
"github.com/docker/docker/api/types"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/container"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libcontainerd/local"
"github.com/docker/docker/libcontainerd/remote"
"github.com/docker/docker/libnetwork"
@ -26,7 +24,6 @@ import (
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/parsers/operatingsystem"
"github.com/docker/docker/pkg/platform"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/runconfig"
@ -513,70 +510,6 @@ func driverOptions(_ *config.Config) nwconfig.Option {
return nil
}
func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
c.Lock()
task, err := c.GetRunningTask()
c.Unlock()
if err != nil {
return nil, err
}
// Obtain the stats from HCS via libcontainerd
stats, err := task.Stats(context.Background())
if err != nil {
if errdefs.IsNotFound(err) {
return nil, containerNotFound(c.ID)
}
return nil, err
}
// Start with an empty structure
s := &types.StatsJSON{}
s.Stats.Read = stats.Read
s.Stats.NumProcs = platform.NumProcs()
if stats.HCSStats != nil {
hcss := stats.HCSStats
// Populate the CPU/processor statistics
s.CPUStats = types.CPUStats{
CPUUsage: types.CPUUsage{
TotalUsage: hcss.Processor.TotalRuntime100ns,
UsageInKernelmode: hcss.Processor.RuntimeKernel100ns,
UsageInUsermode: hcss.Processor.RuntimeUser100ns,
},
}
// Populate the memory statistics
s.MemoryStats = types.MemoryStats{
Commit: hcss.Memory.UsageCommitBytes,
CommitPeak: hcss.Memory.UsageCommitPeakBytes,
PrivateWorkingSet: hcss.Memory.UsagePrivateWorkingSetBytes,
}
// Populate the storage statistics
s.StorageStats = types.StorageStats{
ReadCountNormalized: hcss.Storage.ReadCountNormalized,
ReadSizeBytes: hcss.Storage.ReadSizeBytes,
WriteCountNormalized: hcss.Storage.WriteCountNormalized,
WriteSizeBytes: hcss.Storage.WriteSizeBytes,
}
// Populate the network statistics
s.Networks = make(map[string]types.NetworkStats)
for _, nstats := range hcss.Network {
s.Networks[nstats.EndpointId] = types.NetworkStats{
RxBytes: nstats.BytesReceived,
RxPackets: nstats.PacketsReceived,
RxDropped: nstats.DroppedPacketsIncoming,
TxBytes: nstats.BytesSent,
TxPackets: nstats.PacketsSent,
TxDropped: nstats.DroppedPacketsOutgoing,
}
}
}
return s, nil
}
// setDefaultIsolation determine the default isolation mode for the
// daemon to run in. This is only applicable on Windows
func (daemon *Daemon) setDefaultIsolation() error {

View file

@ -4,11 +4,252 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"strings"
statsV1 "github.com/containerd/cgroups/v3/cgroup1/stats"
statsV2 "github.com/containerd/cgroups/v3/cgroup2/stats"
"github.com/docker/docker/api/types"
"github.com/docker/docker/container"
"github.com/pkg/errors"
)
func copyBlkioEntry(entries []*statsV1.BlkIOEntry) []types.BlkioStatEntry {
out := make([]types.BlkioStatEntry, len(entries))
for i, re := range entries {
out[i] = types.BlkioStatEntry{
Major: re.Major,
Minor: re.Minor,
Op: re.Op,
Value: re.Value,
}
}
return out
}
func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
c.Lock()
task, err := c.GetRunningTask()
c.Unlock()
if err != nil {
return nil, err
}
cs, err := task.Stats(context.Background())
if err != nil {
if strings.Contains(err.Error(), "container not found") {
return nil, containerNotFound(c.ID)
}
return nil, err
}
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),
IoServicedRecursive: copyBlkioEntry(stats.Blkio.IoServicedRecursive),
IoQueuedRecursive: copyBlkioEntry(stats.Blkio.IoQueuedRecursive),
IoServiceTimeRecursive: copyBlkioEntry(stats.Blkio.IoServiceTimeRecursive),
IoWaitTimeRecursive: copyBlkioEntry(stats.Blkio.IoWaitTimeRecursive),
IoMergedRecursive: copyBlkioEntry(stats.Blkio.IoMergedRecursive),
IoTimeRecursive: copyBlkioEntry(stats.Blkio.IoTimeRecursive),
SectorsRecursive: copyBlkioEntry(stats.Blkio.SectorsRecursive),
}
}
if stats.CPU != nil {
s.CPUStats = types.CPUStats{
CPUUsage: types.CPUUsage{
TotalUsage: stats.CPU.Usage.Total,
PercpuUsage: stats.CPU.Usage.PerCPU,
UsageInKernelmode: stats.CPU.Usage.Kernel,
UsageInUsermode: stats.CPU.Usage.User,
},
ThrottlingData: types.ThrottlingData{
Periods: stats.CPU.Throttling.Periods,
ThrottledPeriods: stats.CPU.Throttling.ThrottledPeriods,
ThrottledTime: stats.CPU.Throttling.ThrottledTime,
},
}
}
if stats.Memory != nil {
raw := map[string]uint64{
"cache": stats.Memory.Cache,
"rss": stats.Memory.RSS,
"rss_huge": stats.Memory.RSSHuge,
"mapped_file": stats.Memory.MappedFile,
"dirty": stats.Memory.Dirty,
"writeback": stats.Memory.Writeback,
"pgpgin": stats.Memory.PgPgIn,
"pgpgout": stats.Memory.PgPgOut,
"pgfault": stats.Memory.PgFault,
"pgmajfault": stats.Memory.PgMajFault,
"inactive_anon": stats.Memory.InactiveAnon,
"active_anon": stats.Memory.ActiveAnon,
"inactive_file": stats.Memory.InactiveFile,
"active_file": stats.Memory.ActiveFile,
"unevictable": stats.Memory.Unevictable,
"hierarchical_memory_limit": stats.Memory.HierarchicalMemoryLimit,
"hierarchical_memsw_limit": stats.Memory.HierarchicalSwapLimit,
"total_cache": stats.Memory.TotalCache,
"total_rss": stats.Memory.TotalRSS,
"total_rss_huge": stats.Memory.TotalRSSHuge,
"total_mapped_file": stats.Memory.TotalMappedFile,
"total_dirty": stats.Memory.TotalDirty,
"total_writeback": stats.Memory.TotalWriteback,
"total_pgpgin": stats.Memory.TotalPgPgIn,
"total_pgpgout": stats.Memory.TotalPgPgOut,
"total_pgfault": stats.Memory.TotalPgFault,
"total_pgmajfault": stats.Memory.TotalPgMajFault,
"total_inactive_anon": stats.Memory.TotalInactiveAnon,
"total_active_anon": stats.Memory.TotalActiveAnon,
"total_inactive_file": stats.Memory.TotalInactiveFile,
"total_active_file": stats.Memory.TotalActiveFile,
"total_unevictable": stats.Memory.TotalUnevictable,
}
if stats.Memory.Usage != nil {
s.MemoryStats = types.MemoryStats{
Stats: raw,
Usage: stats.Memory.Usage.Usage,
MaxUsage: stats.Memory.Usage.Max,
Limit: stats.Memory.Usage.Limit,
Failcnt: stats.Memory.Usage.Failcnt,
}
} else {
s.MemoryStats = types.MemoryStats{
Stats: raw,
}
}
// 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
}
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 {
s.MemoryStats = types.MemoryStats{
// Stats is not compatible with v1
Stats: map[string]uint64{
"anon": stats.Memory.Anon,
"file": stats.Memory.File,
"kernel_stack": stats.Memory.KernelStack,
"slab": stats.Memory.Slab,
"sock": stats.Memory.Sock,
"shmem": stats.Memory.Shmem,
"file_mapped": stats.Memory.FileMapped,
"file_dirty": stats.Memory.FileDirty,
"file_writeback": stats.Memory.FileWriteback,
"anon_thp": stats.Memory.AnonThp,
"inactive_anon": stats.Memory.InactiveAnon,
"active_anon": stats.Memory.ActiveAnon,
"inactive_file": stats.Memory.InactiveFile,
"active_file": stats.Memory.ActiveFile,
"unevictable": stats.Memory.Unevictable,
"slab_reclaimable": stats.Memory.SlabReclaimable,
"slab_unreclaimable": stats.Memory.SlabUnreclaimable,
"pgfault": stats.Memory.Pgfault,
"pgmajfault": stats.Memory.Pgmajfault,
"workingset_refault": stats.Memory.WorkingsetRefault,
"workingset_activate": stats.Memory.WorkingsetActivate,
"workingset_nodereclaim": stats.Memory.WorkingsetNodereclaim,
"pgrefill": stats.Memory.Pgrefill,
"pgscan": stats.Memory.Pgscan,
"pgsteal": stats.Memory.Pgsteal,
"pgactivate": stats.Memory.Pgactivate,
"pgdeactivate": stats.Memory.Pgdeactivate,
"pglazyfree": stats.Memory.Pglazyfree,
"pglazyfreed": stats.Memory.Pglazyfreed,
"thp_fault_alloc": stats.Memory.ThpFaultAlloc,
"thp_collapse_alloc": stats.Memory.ThpCollapseAlloc,
},
Usage: stats.Memory.Usage,
// MaxUsage is not supported
Limit: stats.Memory.UsageLimit,
}
// 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.MemoryEvents != nil {
// Failcnt is set to the "oom" field of the "memory.events" file.
// See https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
s.MemoryStats.Failcnt = stats.MemoryEvents.Oom
}
}
if stats.Pids != nil {
s.PidsStats = types.PidsStats{
Current: stats.Pids.Current,
Limit: stats.Pids.Limit,
}
}
return s, nil
}
// Resolve Network SandboxID in case the container reuse another container's network stack
func (daemon *Daemon) getNetworkSandboxID(c *container.Container) (string, error) {
curr := c

View file

@ -1,10 +1,78 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/platform"
)
func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
c.Lock()
task, err := c.GetRunningTask()
c.Unlock()
if err != nil {
return nil, err
}
// Obtain the stats from HCS via libcontainerd
stats, err := task.Stats(context.Background())
if err != nil {
if errdefs.IsNotFound(err) {
return nil, containerNotFound(c.ID)
}
return nil, err
}
// Start with an empty structure
s := &types.StatsJSON{}
s.Stats.Read = stats.Read
s.Stats.NumProcs = platform.NumProcs()
if stats.HCSStats != nil {
hcss := stats.HCSStats
// Populate the CPU/processor statistics
s.CPUStats = types.CPUStats{
CPUUsage: types.CPUUsage{
TotalUsage: hcss.Processor.TotalRuntime100ns,
UsageInKernelmode: hcss.Processor.RuntimeKernel100ns,
UsageInUsermode: hcss.Processor.RuntimeUser100ns,
},
}
// Populate the memory statistics
s.MemoryStats = types.MemoryStats{
Commit: hcss.Memory.UsageCommitBytes,
CommitPeak: hcss.Memory.UsageCommitPeakBytes,
PrivateWorkingSet: hcss.Memory.UsagePrivateWorkingSetBytes,
}
// Populate the storage statistics
s.StorageStats = types.StorageStats{
ReadCountNormalized: hcss.Storage.ReadCountNormalized,
ReadSizeBytes: hcss.Storage.ReadSizeBytes,
WriteCountNormalized: hcss.Storage.WriteCountNormalized,
WriteSizeBytes: hcss.Storage.WriteSizeBytes,
}
// Populate the network statistics
s.Networks = make(map[string]types.NetworkStats)
for _, nstats := range hcss.Network {
s.Networks[nstats.EndpointId] = types.NetworkStats{
RxBytes: nstats.BytesReceived,
RxPackets: nstats.PacketsReceived,
RxDropped: nstats.DroppedPacketsIncoming,
TxBytes: nstats.BytesSent,
TxPackets: nstats.PacketsSent,
TxDropped: nstats.DroppedPacketsOutgoing,
}
}
}
return s, nil
}
// Windows network stats are obtained directly through HCS, hence this is a no-op.
func (daemon *Daemon) getNetworkStats(c *container.Container) (map[string]types.NetworkStats, error) {
return make(map[string]types.NetworkStats), nil