@@ -25,6 +25,7 @@ import (
2525 "os"
2626 "text/tabwriter"
2727
28+ wstats "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats"
2829 v1 "github.com/containerd/cgroups/stats/v1"
2930 "github.com/containerd/containerd/cmd/ctr/commands"
3031 "github.com/containerd/typeurl"
@@ -77,30 +78,36 @@ var metricsCommand = cli.Command{
7778 if err != nil {
7879 return err
7980 }
80- data , ok := anydata .(* v1.Metrics )
81- if ! ok {
82- return errors .New ("cannot convert metric data to cgroups.Metrics" )
81+ var (
82+ data * v1.Metrics
83+ windowsStats * wstats.Statistics
84+ )
85+ switch v := anydata .(type ) {
86+ case * v1.Metrics :
87+ data = v
88+ case * wstats.Statistics :
89+ windowsStats = v
90+ default :
91+ return errors .New ("cannot convert metric data to cgroups.Metrics or windows.Statistics" )
8392 }
8493
8594 switch context .String (formatFlag ) {
8695 case formatTable :
8796 w := tabwriter .NewWriter (os .Stdout , 1 , 8 , 4 , ' ' , 0 )
8897 fmt .Fprintf (w , "ID\t TIMESTAMP\t \n " )
8998 fmt .Fprintf (w , "%s\t %s\t \n \n " , metric .ID , metric .Timestamp )
90-
91- fmt .Fprintf (w , "METRIC\t VALUE\t \n " )
92- if data .Memory != nil {
93- fmt .Fprintf (w , "memory.usage_in_bytes\t %d\t \n " , data .Memory .Usage .Usage )
94- fmt .Fprintf (w , "memory.limit_in_bytes\t %d\t \n " , data .Memory .Usage .Limit )
95- fmt .Fprintf (w , "memory.stat.cache\t %d\t \n " , data .Memory .TotalCache )
96- }
97- if data .CPU != nil {
98- fmt .Fprintf (w , "cpuacct.usage\t %d\t \n " , data .CPU .Usage .Total )
99- fmt .Fprintf (w , "cpuacct.usage_percpu\t %v\t \n " , data .CPU .Usage .PerCPU )
100- }
101- if data .Pids != nil {
102- fmt .Fprintf (w , "pids.current\t %v\t \n " , data .Pids .Current )
103- fmt .Fprintf (w , "pids.limit\t %v\t \n " , data .Pids .Limit )
99+ if data != nil {
100+ printCgroupMetricsTable (w , data )
101+ } else {
102+ if windowsStats .GetLinux () != nil {
103+ printCgroupMetricsTable (w , windowsStats .GetLinux ())
104+ } else if windowsStats .GetWindows () != nil {
105+ printWindowsContainerStatistics (w , windowsStats .GetWindows ())
106+ }
107+ // Print VM stats if its isolated
108+ if windowsStats .VM != nil {
109+ printWindowsVMStatistics (w , windowsStats .VM )
110+ }
104111 }
105112 return w .Flush ()
106113 case formatJSON :
@@ -115,3 +122,61 @@ var metricsCommand = cli.Command{
115122 }
116123 },
117124}
125+
126+ func printCgroupMetricsTable (w * tabwriter.Writer , data * v1.Metrics ) {
127+ fmt .Fprintf (w , "METRIC\t VALUE\t \n " )
128+ if data .Memory != nil {
129+ fmt .Fprintf (w , "memory.usage_in_bytes\t %d\t \n " , data .Memory .Usage .Usage )
130+ fmt .Fprintf (w , "memory.limit_in_bytes\t %d\t \n " , data .Memory .Usage .Limit )
131+ fmt .Fprintf (w , "memory.stat.cache\t %d\t \n " , data .Memory .TotalCache )
132+ }
133+ if data .CPU != nil {
134+ fmt .Fprintf (w , "cpuacct.usage\t %d\t \n " , data .CPU .Usage .Total )
135+ fmt .Fprintf (w , "cpuacct.usage_percpu\t %v\t \n " , data .CPU .Usage .PerCPU )
136+ }
137+ if data .Pids != nil {
138+ fmt .Fprintf (w , "pids.current\t %v\t \n " , data .Pids .Current )
139+ fmt .Fprintf (w , "pids.limit\t %v\t \n " , data .Pids .Limit )
140+ }
141+ }
142+
143+ func printWindowsContainerStatistics (w * tabwriter.Writer , stats * wstats.WindowsContainerStatistics ) {
144+ fmt .Fprintf (w , "METRIC\t VALUE\t \n " )
145+ fmt .Fprintf (w , "timestamp\t %s\t \n " , stats .Timestamp )
146+ fmt .Fprintf (w , "start_time\t %s\t \n " , stats .ContainerStartTime )
147+ fmt .Fprintf (w , "uptime_ns\t %d\t \n " , stats .UptimeNS )
148+ if stats .Processor != nil {
149+ fmt .Fprintf (w , "cpu.total_runtime_ns\t %d\t \n " , stats .Processor .TotalRuntimeNS )
150+ fmt .Fprintf (w , "cpu.runtime_user_ns\t %d\t \n " , stats .Processor .RuntimeUserNS )
151+ fmt .Fprintf (w , "cpu.runtime_kernel_ns\t %d\t \n " , stats .Processor .RuntimeUserNS )
152+ }
153+ if stats .Memory != nil {
154+ fmt .Fprintf (w , "memory.commit_bytes\t %d\t \n " , stats .Memory .MemoryUsageCommitBytes )
155+ fmt .Fprintf (w , "memory.commit_peak_bytes\t %d\t \n " , stats .Memory .MemoryUsageCommitPeakBytes )
156+ fmt .Fprintf (w , "memory.private_working_set_bytes\t %d\t \n " , stats .Memory .MemoryUsagePrivateWorkingSetBytes )
157+ }
158+ if stats .Storage != nil {
159+ fmt .Fprintf (w , "storage.read_count_normalized\t %d\t \n " , stats .Storage .ReadCountNormalized )
160+ fmt .Fprintf (w , "storage.read_size_bytes\t %d\t \n " , stats .Storage .ReadSizeBytes )
161+ fmt .Fprintf (w , "storage.write_count_normalized\t %d\t \n " , stats .Storage .WriteCountNormalized )
162+ fmt .Fprintf (w , "storage.write_size_bytes\t %d\t \n " , stats .Storage .WriteSizeBytes )
163+ }
164+ }
165+
166+ func printWindowsVMStatistics (w * tabwriter.Writer , stats * wstats.VirtualMachineStatistics ) {
167+ fmt .Fprintf (w , "METRIC\t VALUE\t \n " )
168+ if stats .Processor != nil {
169+ fmt .Fprintf (w , "vm.cpu.total_runtime_ns\t %d\t \n " , stats .Processor .TotalRuntimeNS )
170+ }
171+ if stats .Memory != nil {
172+ fmt .Fprintf (w , "vm.memory.working_set_bytes\t %d\t \n " , stats .Memory .WorkingSetBytes )
173+ fmt .Fprintf (w , "vm.memory.virtual_node_count\t %d\t \n " , stats .Memory .VirtualNodeCount )
174+ fmt .Fprintf (w , "vm.memory.available\t %d\t \n " , stats .Memory .VmMemory .AvailableMemory )
175+ fmt .Fprintf (w , "vm.memory.available_buffer\t %d\t \n " , stats .Memory .VmMemory .AvailableMemoryBuffer )
176+ fmt .Fprintf (w , "vm.memory.reserved\t %d\t \n " , stats .Memory .VmMemory .ReservedMemory )
177+ fmt .Fprintf (w , "vm.memory.assigned\t %d\t \n " , stats .Memory .VmMemory .AssignedMemory )
178+ fmt .Fprintf (w , "vm.memory.slp_active\t %t\t \n " , stats .Memory .VmMemory .SlpActive )
179+ fmt .Fprintf (w , "vm.memory.balancing_enabled\t %t\t \n " , stats .Memory .VmMemory .BalancingEnabled )
180+ fmt .Fprintf (w , "vm.memory.dm_operation_in_progress\t %t\t \n " , stats .Memory .VmMemory .DmOperationInProgress )
181+ }
182+ }
0 commit comments