diff --git a/container/libcontainer/helpers.go b/container/libcontainer/helpers.go index 315bdf67..d11b5865 100644 --- a/container/libcontainer/helpers.go +++ b/container/libcontainer/helpers.go @@ -37,35 +37,40 @@ func toContainerStats(libcontainerStats *libcontainer.ContainerStats) *info.Cont s := libcontainerStats.CgroupStats ret := new(info.ContainerStats) ret.Timestamp = time.Now() - ret.Cpu = new(info.CpuStats) - ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode - ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode - n := len(s.CpuStats.CpuUsage.PercpuUsage) - ret.Cpu.Usage.PerCpu = make([]uint64, n) - ret.Cpu.Usage.Total = 0 - for i := 0; i < n; i++ { - ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i] - ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i] - } - ret.Memory = new(info.MemoryStats) - ret.Memory.Usage = s.MemoryStats.Usage - if v, ok := s.MemoryStats.Stats["pgfault"]; ok { - ret.Memory.ContainerData.Pgfault = v - ret.Memory.HierarchicalData.Pgfault = v - } - if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok { - ret.Memory.ContainerData.Pgmajfault = v - ret.Memory.HierarchicalData.Pgmajfault = v - } - if v, ok := s.MemoryStats.Stats["total_inactive_anon"]; ok { - ret.Memory.WorkingSet = ret.Memory.Usage - v - if v, ok := s.MemoryStats.Stats["total_active_file"]; ok { - ret.Memory.WorkingSet -= v + if s != nil { + ret.Cpu = new(info.CpuStats) + ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode + ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode + n := len(s.CpuStats.CpuUsage.PercpuUsage) + ret.Cpu.Usage.PerCpu = make([]uint64, n) + + ret.Cpu.Usage.Total = 0 + for i := 0; i < n; i++ { + ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i] + ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i] + } + ret.Memory = new(info.MemoryStats) + ret.Memory.Usage = s.MemoryStats.Usage + if v, ok := s.MemoryStats.Stats["pgfault"]; ok { + ret.Memory.ContainerData.Pgfault = v + ret.Memory.HierarchicalData.Pgfault = v + } + if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok { + ret.Memory.ContainerData.Pgmajfault = v + ret.Memory.HierarchicalData.Pgmajfault = v + } + if v, ok := s.MemoryStats.Stats["total_inactive_anon"]; ok { + ret.Memory.WorkingSet = ret.Memory.Usage - v + if v, ok := s.MemoryStats.Stats["total_active_file"]; ok { + ret.Memory.WorkingSet -= v + } } } // TODO(vishh): Perform a deep copy or alias libcontainer network stats. - ret.Network = (*info.NetworkStats)(&libcontainerStats.NetworkStats) + if libcontainerStats.NetworkStats != nil { + ret.Network = (*info.NetworkStats)(libcontainerStats.NetworkStats) + } return ret } diff --git a/info/container.go b/info/container.go index 194f77a3..48252a9c 100644 --- a/info/container.go +++ b/info/container.go @@ -241,21 +241,21 @@ type MemoryStatsMemoryData struct { type NetworkStats struct { // Cumulative count of bytes received. - RxBytes uint64 `json:"rx_bytes,omitempty"` + RxBytes uint64 `json:"rx_bytes"` // Cumulative count of packets received. - RxPackets uint64 `json:"rx_packets,omitempty"` + RxPackets uint64 `json:"rx_packets"` // Cumulative count of receive errors encountered. - RxErrors uint64 `json:"rx_errors,omitempty"` + RxErrors uint64 `json:"rx_errors"` // Cumulative count of packets dropped while receiving. - RxDropped uint64 `json:"rx_dropped,omitempty"` + RxDropped uint64 `json:"rx_dropped"` // Cumulative count of bytes transmitted. - TxBytes uint64 `json:"tx_bytes,omitempty"` + TxBytes uint64 `json:"tx_bytes"` // Cumulative count of packets transmitted. - TxPackets uint64 `json:"tx_packets,omitempty"` + TxPackets uint64 `json:"tx_packets"` // Cumulative count of transmit errors encountered. - TxErrors uint64 `json:"tx_errors,omitempty"` + TxErrors uint64 `json:"tx_errors"` // Cumulative count of packets dropped while transmitting. - TxDropped uint64 `json:"tx_dropped,omitempty"` + TxDropped uint64 `json:"tx_dropped"` } type ContainerStats struct { diff --git a/pages/containers.go b/pages/containers.go index b3302b17..be7c2e26 100644 --- a/pages/containers.go +++ b/pages/containers.go @@ -57,6 +57,7 @@ type pageData struct { ResourcesAvailable bool CpuAvailable bool MemoryAvailable bool + NetworkAvailable bool } func init() { @@ -204,6 +205,14 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) } } + networkStatsAvailable := false + for _, stat := range cont.Stats { + if stat.Network != nil { + networkStatsAvailable = true + break + } + } + data := &pageData{ ContainerName: displayName, // TODO(vmarmol): Only use strings for this. @@ -215,6 +224,7 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) ResourcesAvailable: cont.Spec.Cpu != nil || cont.Spec.Memory != nil, CpuAvailable: cont.Spec.Cpu != nil, MemoryAvailable: cont.Spec.Memory != nil, + NetworkAvailable: networkStatsAvailable, } err = pageTemplate.Execute(w, data) if err != nil { diff --git a/pages/containers_html.go b/pages/containers_html.go index fc5f9811..8cbaa3c3 100644 --- a/pages/containers_html.go +++ b/pages/containers_html.go @@ -16,153 +16,160 @@ package pages const containersHtmlTemplate = ` - - cAdvisor - Container {{.ContainerName}} - - + + cAdvisor - Container {{.ContainerName}} + + - - + + - + - - - - + + + + - - - -
- -
- - -
- {{if .Subcontainers}} -
- -
- {{range $subcontainer := .Subcontainers}} - {{containerLink $subcontainer false "list-group-item"}} + + + +
+ +
+ + +
+ {{if .Subcontainers}} +
+ +
+ {{range $subcontainer := .Subcontainers}} + {{containerLink $subcontainer false "list-group-item"}} + {{end}} +
+
+ {{end}} + {{if .ResourcesAvailable}} +
+ + {{if .CpuAvailable}} +
    +
  • CPU
  • + {{if .Spec.Cpu.Limit}} +
  • Limit {{printCores .Spec.Cpu.Limit}} cores
  • + {{end}} + {{if .Spec.Cpu.MaxLimit}} +
  • Max Limit {{printCores .Spec.Cpu.MaxLimit}} cores
  • + {{end}} + {{if .Spec.Cpu.Mask}} +
  • Allowed Cores {{printMask .Spec.Cpu.Mask .MachineInfo.NumCores}}
  • + {{end}} +
+ {{end}} + {{if .MemoryAvailable}} +
    +
  • Memory
  • + {{if .Spec.Memory.Reservation}} +
  • Reservation {{printMegabytes .Spec.Memory.Reservation}} MB
  • + {{end}} + {{if .Spec.Memory.Limit}} +
  • Limit {{printMegabytes .Spec.Memory.Limit}} MB
  • + {{end}} + {{if .Spec.Memory.SwapLimit}} +
  • Swap Limit {{printMegabytes .Spec.Memory.SwapLimit}} MB
  • + {{end}} +
+ {{end}} +
+
+ +
+
+

Overview

+
+
+
+
+ {{if .CpuAvailable}} +
+
+

CPU

+
+
+

Total Usage

+
+

Usage per Core

+
+

Usage Breakdown

+
+
+
+ {{end}} + {{if .MemoryAvailable}} +
+
+

Memory

+
+
+

Total Usage

+
+
+
+

Usage Breakdown

+
+
+
+ Hot Memory +
+
+ Cold Memory +
+
+
+
+ {{ getMemoryUsage .Stats }} MB ({{ getMemoryUsagePercent .Spec .Stats .MachineInfo}}%) +
+
+

Page Faults

+
+
+
+ {{end}} + {{if .NetworkAvailable}} +
+
+

Network

+
+
+

Throughput

+
+
+
+

Errors

+
+
+
+ {{end}} +
{{end}}
-
- {{end}} - {{if .ResourcesAvailable}} -
- - {{if .CpuAvailable}} -
    -
  • CPU
  • - {{if .Spec.Cpu.Limit}} -
  • Limit {{printCores .Spec.Cpu.Limit}} cores
  • - {{end}} - {{if .Spec.Cpu.MaxLimit}} -
  • Max Limit {{printCores .Spec.Cpu.MaxLimit}} cores
  • - {{end}} - {{if .Spec.Cpu.Mask}} -
  • Allowed Cores {{printMask .Spec.Cpu.Mask .MachineInfo.NumCores}}
  • - {{end}} -
- {{end}} - {{if .MemoryAvailable}} -
    -
  • Memory
  • - {{if .Spec.Memory.Reservation}} -
  • Reservation {{printMegabytes .Spec.Memory.Reservation}} MB
  • - {{end}} - {{if .Spec.Memory.Limit}} -
  • Limit {{printMegabytes .Spec.Memory.Limit}} MB
  • - {{end}} - {{if .Spec.Memory.SwapLimit}} -
  • Swap Limit {{printMegabytes .Spec.Memory.SwapLimit}} MB
  • - {{end}} -
- {{end}} -
-
- -
-
-

Overview

-
-
-
-
- {{if .CpuAvailable}} -
-
-

CPU

-
-
-

Total Usage

-
-

Usage per Core

-
-

Usage Breakdown

-
-
-
- {{end}} - {{if .MemoryAvailable}} -
-
-

Memory

-
-
-

Total Usage

-
-
-
-

Usage Breakdown

-
-
-
- Hot Memory -
-
- Cold Memory -
-
-
-
- {{ getMemoryUsage .Stats }} MB ({{ getMemoryUsagePercent .Spec .Stats .MachineInfo}}%) -
-
-

Page Faults

-
-
-
- {{end}} -
-
-

Network

-
-
-
-
-
-
- {{end}} -
- - + + ` diff --git a/pages/static/containers_js.go b/pages/static/containers_js.go index a1514d4d..113f9122 100644 --- a/pages/static/containers_js.go +++ b/pages/static/containers_js.go @@ -234,7 +234,7 @@ function drawNetworkBytes(elementId, machineInfo, stats) { elements.push(cur.network.rx_bytes - prev.network.rx_bytes); data.push(elements); } - drawLineChart(titles, data, elementId, "Bytes"); + drawLineChart(titles, data, elementId, "Bytes per second"); } // Draw the graph for network errors @@ -252,7 +252,7 @@ function drawNetworkErrors(elementId, machineInfo, stats) { elements.push(cur.network.rx_errors - prev.network.rx_errors); data.push(elements); } - drawLineChart(titles, data, elementId, "Errors"); + drawLineChart(titles, data, elementId, "Errors per second"); } // Expects an array of closures to call. After each execution the JS runtime is given control back before continuing.