Merge remote-tracking branch 'upstream/master'
Docker-DCO-1.1-Signed-off-by: Rohit Jnagal <jnagal@google.com> (github: rjnagal)
This commit is contained in:
commit
54fbc922a5
13
.travis.yml
13
.travis.yml
@ -1,9 +1,12 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.1
|
- 1.2
|
||||||
|
before_script:
|
||||||
|
- go get github.com/stretchr/testify/mock
|
||||||
|
- go get github.com/kr/pretty
|
||||||
script:
|
script:
|
||||||
- go test -v -race github.com/google/cadvisor/container
|
- go test -v -race github.com/google/cadvisor/container
|
||||||
- go test -v -race github.com/google/cadvisor/info
|
- go test -v github.com/google/cadvisor/info
|
||||||
- go test -v -race github.com/google/cadvisor/client
|
- go test -v github.com/google/cadvisor/client
|
||||||
- go test -v -race github.com/google/cadvisor/sampling
|
- go test -v github.com/google/cadvisor/sampling
|
||||||
- go build -race github.com/google/cadvisor
|
- go build github.com/google/cadvisor
|
||||||
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
FROM google/golang-runtime
|
||||||
|
MAINTAINER dengnan@google.com vmarmol@google.com proppy@google.com
|
||||||
|
|
||||||
|
# TODO(vmarmol): Build from source.
|
||||||
|
# Get lmctfy and its dependencies.
|
||||||
|
RUN apt-get update -y --force-yes && apt-get install -y --no-install-recommends --force-yes pkg-config libapparmor1
|
||||||
|
ADD http://storage.googleapis.com/cadvisor-bin/lmctfy/libre2.so.0.0.0 /usr/lib/libre2.so.0
|
||||||
|
ADD http://storage.googleapis.com/cadvisor-bin/lmctfy/lmctfy /usr/bin/lmctfy
|
||||||
|
RUN chmod +x /usr/bin/lmctfy
|
||||||
|
|
||||||
|
# Install libprotobuf8.
|
||||||
|
ADD http://storage.googleapis.com/cadvisor-bin/lmctfy/libprotobuf8_2.5.0-9_amd64.deb /tmp/libprotobuf8_2.5.0-9_amd64.deb
|
||||||
|
ADD http://storage.googleapis.com/cadvisor-bin/lmctfy/libc6_2.19-1_amd64.deb /tmp/libc6_2.19-1_amd64.deb
|
||||||
|
RUN dpkg -i /tmp/libc6_2.19-1_amd64.deb /tmp/libprotobuf8_2.5.0-9_amd64.deb
|
||||||
|
|
||||||
|
# The image builds the app and exposes it on 8080.
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
"github.com/google/cadvisor/container/docker"
|
"github.com/google/cadvisor/container/docker"
|
||||||
"github.com/google/cadvisor/container/lmctfy"
|
"github.com/google/cadvisor/container/lmctfy"
|
||||||
|
"github.com/google/cadvisor/info"
|
||||||
"github.com/google/cadvisor/manager"
|
"github.com/google/cadvisor/manager"
|
||||||
"github.com/google/cadvisor/pages"
|
"github.com/google/cadvisor/pages"
|
||||||
"github.com/google/cadvisor/pages/static"
|
"github.com/google/cadvisor/pages/static"
|
||||||
@ -92,6 +93,7 @@ func main() {
|
|||||||
|
|
||||||
go containerManager.Start()
|
go containerManager.Start()
|
||||||
|
|
||||||
|
log.Printf("Starting cAdvisor version: %q", info.VERSION)
|
||||||
log.Print("About to serve on port ", *argPort)
|
log.Print("About to serve on port ", *argPort)
|
||||||
|
|
||||||
addr := fmt.Sprintf(":%v", *argPort)
|
addr := fmt.Sprintf(":%v", *argPort)
|
||||||
|
@ -30,6 +30,7 @@ type ListType int
|
|||||||
|
|
||||||
// Interface for container operation handlers.
|
// Interface for container operation handlers.
|
||||||
type ContainerHandler interface {
|
type ContainerHandler interface {
|
||||||
|
ContainerReference() (info.ContainerReference, error)
|
||||||
GetSpec() (*info.ContainerSpec, error)
|
GetSpec() (*info.ContainerSpec, error)
|
||||||
GetStats() (*info.ContainerStats, error)
|
GetStats() (*info.ContainerStats, error)
|
||||||
ListContainers(listType ListType) ([]info.ContainerReference, error)
|
ListContainers(listType ListType) ([]info.ContainerReference, error)
|
||||||
|
@ -40,11 +40,11 @@ func (self *dockerFactory) NewContainerHandler(name string) (handler container.C
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler = &dockerContainerHandler{
|
handler, err = newDockerContainerHandler(
|
||||||
client: client,
|
client,
|
||||||
name: name,
|
name,
|
||||||
machineInfoFactory: self.machineInfoFactory,
|
self.machineInfoFactory,
|
||||||
}
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,43 @@ import (
|
|||||||
type dockerContainerHandler struct {
|
type dockerContainerHandler struct {
|
||||||
client *docker.Client
|
client *docker.Client
|
||||||
name string
|
name string
|
||||||
|
aliases []string
|
||||||
machineInfoFactory info.MachineInfoFactory
|
machineInfoFactory info.MachineInfoFactory
|
||||||
container.NoStatsSummary
|
container.NoStatsSummary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newDockerContainerHandler(
|
||||||
|
client *docker.Client,
|
||||||
|
name string,
|
||||||
|
machineInfoFactory info.MachineInfoFactory,
|
||||||
|
) (container.ContainerHandler, error) {
|
||||||
|
handler := &dockerContainerHandler{
|
||||||
|
client: client,
|
||||||
|
name: name,
|
||||||
|
machineInfoFactory: machineInfoFactory,
|
||||||
|
}
|
||||||
|
if !handler.isDockerContainer() {
|
||||||
|
return handler, nil
|
||||||
|
}
|
||||||
|
_, id, err := handler.splitName()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid docker container %v: %v", name, err)
|
||||||
|
}
|
||||||
|
ctnr, err := client.InspectContainer(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to inspect container %v: %v", name, err)
|
||||||
|
}
|
||||||
|
handler.aliases = append(handler.aliases, path.Join("/docker", ctnr.Name))
|
||||||
|
return handler, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return info.ContainerReference{
|
||||||
|
Name: self.name,
|
||||||
|
Aliases: self.aliases,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) splitName() (string, string, error) {
|
func (self *dockerContainerHandler) splitName() (string, string, error) {
|
||||||
parent, id := path.Split(self.name)
|
parent, id := path.Split(self.name)
|
||||||
cgroupSelf, err := os.Open("/proc/self/cgroup")
|
cgroupSelf, err := os.Open("/proc/self/cgroup")
|
||||||
|
@ -114,7 +114,7 @@ func (self *factoryManager) NewContainerHandler(path string) (ContainerHandler,
|
|||||||
err := fmt.Errorf("nil factory for container %v", path)
|
err := fmt.Errorf("nil factory for container %v", path)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Printf("container handler factory for %v is %v\n", path, factory)
|
log.Printf("Container handler factory for %v is %v\n", path, factory)
|
||||||
return factory.NewContainerHandler(path)
|
return factory.NewContainerHandler(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,10 @@ type containerListFilter struct {
|
|||||||
NoStatsSummary
|
NoStatsSummary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *containerListFilter) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return self.handler.ContainerReference()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *containerListFilter) GetSpec() (*info.ContainerSpec, error) {
|
func (self *containerListFilter) GetSpec() (*info.ContainerSpec, error) {
|
||||||
return self.handler.GetSpec()
|
return self.handler.GetSpec()
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,11 @@ func (self *mockContainerHandler) GetSpec() (*info.ContainerSpec, error) {
|
|||||||
return args.Get(0).(*info.ContainerSpec), args.Error(1)
|
return args.Get(0).(*info.ContainerSpec), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *mockContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
args := self.Called()
|
||||||
|
return args.Get(0).(info.ContainerReference), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandler) GetStats() (*info.ContainerStats, error) {
|
func (self *mockContainerHandler) GetStats() (*info.ContainerStats, error) {
|
||||||
args := self.Called()
|
args := self.Called()
|
||||||
return args.Get(0).(*info.ContainerStats), args.Error(1)
|
return args.Get(0).(*info.ContainerStats), args.Error(1)
|
||||||
|
@ -47,6 +47,10 @@ func New(name string) (container.ContainerHandler, error) {
|
|||||||
return el, nil
|
return el, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *lmctfyContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return info.ContainerReference{Name: self.Name}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getExitCode(err error) int {
|
func getExitCode(err error) int {
|
||||||
msg, ok := err.(*exec.ExitError)
|
msg, ok := err.(*exec.ExitError)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -36,6 +36,10 @@ func (self *percentilesContainerHandlerWrapper) GetSpec() (*info.ContainerSpec,
|
|||||||
return self.handler.GetSpec()
|
return self.handler.GetSpec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *percentilesContainerHandlerWrapper) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return self.handler.ContainerReference()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *percentilesContainerHandlerWrapper) updatePrevStats(stats *info.ContainerStats) {
|
func (self *percentilesContainerHandlerWrapper) updatePrevStats(stats *info.ContainerStats) {
|
||||||
if stats == nil || stats.Cpu == nil || stats.Memory == nil {
|
if stats == nil || stats.Cpu == nil || stats.Memory == nil {
|
||||||
// discard incomplete stats
|
// discard incomplete stats
|
||||||
|
@ -94,6 +94,12 @@ func containerWithTrace(duration time.Duration, cpuUsages []uint64, memUsages []
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *replayTrace) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return info.ContainerReference{
|
||||||
|
Name: "replay",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *replayTrace) GetStats() (*info.ContainerStats, error) {
|
func (self *replayTrace) GetStats() (*info.ContainerStats, error) {
|
||||||
stats := new(info.ContainerStats)
|
stats := new(info.ContainerStats)
|
||||||
stats.Cpu = new(info.CpuStats)
|
stats.Cpu = new(info.CpuStats)
|
||||||
|
18
info/version.go
Normal file
18
info/version.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 info
|
||||||
|
|
||||||
|
// Version of cAdvisor.
|
||||||
|
const VERSION = "0.1.0"
|
@ -91,7 +91,12 @@ func NewContainerData(containerName string) (*containerData, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cont.handler = handler
|
cont.handler = handler
|
||||||
cont.info.Name = containerName
|
ref, err := handler.ContainerReference()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cont.info.Name = ref.Name
|
||||||
|
cont.info.Aliases = ref.Aliases
|
||||||
cont.info.Stats = list.New()
|
cont.info.Stats = list.New()
|
||||||
cont.stop = make(chan bool, 1)
|
cont.stop = make(chan bool, 1)
|
||||||
|
|
||||||
|
@ -124,7 +124,8 @@ func (m *manager) GetContainerInfo(containerName string) (*info.ContainerInfo, e
|
|||||||
// Make a copy of the info for the user.
|
// Make a copy of the info for the user.
|
||||||
ret := &info.ContainerInfo{
|
ret := &info.ContainerInfo{
|
||||||
ContainerReference: info.ContainerReference{
|
ContainerReference: info.ContainerReference{
|
||||||
Name: cinfo.Name,
|
Name: cinfo.Name,
|
||||||
|
Aliases: cinfo.Aliases,
|
||||||
},
|
},
|
||||||
Subcontainers: cinfo.Subcontainers,
|
Subcontainers: cinfo.Subcontainers,
|
||||||
Spec: cinfo.Spec,
|
Spec: cinfo.Spec,
|
||||||
@ -169,9 +170,13 @@ func (m *manager) createContainer(containerName string) (*containerData, error)
|
|||||||
m.containersLock.Lock()
|
m.containersLock.Lock()
|
||||||
defer m.containersLock.Unlock()
|
defer m.containersLock.Unlock()
|
||||||
|
|
||||||
log.Printf("Added container: %s", containerName)
|
// Add the container name and all its aliases.
|
||||||
m.containers[containerName] = cont
|
m.containers[containerName] = cont
|
||||||
|
for _, alias := range cont.info.Aliases {
|
||||||
|
m.containers[alias] = cont
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
log.Printf("Added container: %s (aliases: %s)", containerName, cont.info.Aliases)
|
||||||
|
|
||||||
// Start the container's housekeeping.
|
// Start the container's housekeeping.
|
||||||
cont.Start()
|
cont.Start()
|
||||||
@ -193,9 +198,12 @@ func (m *manager) destroyContainer(containerName string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the container from our records.
|
// Remove the container from our records (and all its aliases).
|
||||||
delete(m.containers, containerName)
|
delete(m.containers, containerName)
|
||||||
log.Printf("Destroyed container: %s", containerName)
|
for _, alias := range cont.info.Aliases {
|
||||||
|
delete(m.containers, alias)
|
||||||
|
}
|
||||||
|
log.Printf("Destroyed container: %s (aliases: %s)", containerName, cont.info.Aliases)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +227,10 @@ func (m *manager) getContainersDiff() (added []info.ContainerReference, removed
|
|||||||
// Determine which were added and which were removed.
|
// Determine which were added and which were removed.
|
||||||
allContainersSet := make(map[string]*containerData)
|
allContainersSet := make(map[string]*containerData)
|
||||||
for name, d := range m.containers {
|
for name, d := range m.containers {
|
||||||
allContainersSet[name] = d
|
// Only add the canonical name.
|
||||||
|
if d.info.Name == name {
|
||||||
|
allContainersSet[name] = d
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, c := range allContainers {
|
for _, c := range allContainers {
|
||||||
delete(allContainersSet, c.Name)
|
delete(allContainersSet, c.Name)
|
||||||
|
@ -37,7 +37,6 @@ var funcMap = template.FuncMap{
|
|||||||
"printMask": printMask,
|
"printMask": printMask,
|
||||||
"printCores": printCores,
|
"printCores": printCores,
|
||||||
"printMegabytes": printMegabytes,
|
"printMegabytes": printMegabytes,
|
||||||
"containerNameEquals": containerNameEquals,
|
|
||||||
"getMemoryUsage": getMemoryUsage,
|
"getMemoryUsage": getMemoryUsage,
|
||||||
"getMemoryUsagePercent": getMemoryUsagePercent,
|
"getMemoryUsagePercent": getMemoryUsagePercent,
|
||||||
"getHotMemoryPercent": getHotMemoryPercent,
|
"getHotMemoryPercent": getHotMemoryPercent,
|
||||||
@ -85,10 +84,6 @@ func containerLink(container info.ContainerReference, basenameOnly bool, cssClas
|
|||||||
return template.HTML(fmt.Sprintf("<a class=\"%s\" href=\"%s%s\">%s</a>", cssClasses, ContainersPage[:len(ContainersPage)-1], containerName, displayName))
|
return template.HTML(fmt.Sprintf("<a class=\"%s\" href=\"%s%s\">%s</a>", cssClasses, ContainersPage[:len(ContainersPage)-1], containerName, displayName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerNameEquals(c1 string, c2 string) bool {
|
|
||||||
return c1 == c2
|
|
||||||
}
|
|
||||||
|
|
||||||
func printMask(mask *info.CpuSpecMask, numCores int) interface{} {
|
func printMask(mask *info.CpuSpecMask, numCores int) interface{} {
|
||||||
// TODO(vmarmol): Detect this correctly.
|
// TODO(vmarmol): Detect this correctly.
|
||||||
// TODO(vmarmol): Support more than 64 cores.
|
// TODO(vmarmol): Support more than 64 cores.
|
||||||
@ -130,25 +125,31 @@ func printMegabytes(bytes uint64) string {
|
|||||||
return strconv.FormatFloat(megabytes, 'f', 3, 64)
|
return strconv.FormatFloat(megabytes, 'f', 3, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toMemoryPercent(usage uint64, spec *info.ContainerSpec) int {
|
func toMemoryPercent(usage uint64, spec *info.ContainerSpec, machine *info.MachineInfo) int {
|
||||||
return int((usage * 100) / (spec.Memory.Limit))
|
// Saturate limit to the machine size.
|
||||||
|
limit := uint64(spec.Memory.Limit)
|
||||||
|
if limit > uint64(machine.MemoryCapacity) {
|
||||||
|
limit = uint64(machine.MemoryCapacity)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int((usage * 100) / limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMemoryUsage(stats []*info.ContainerStats) string {
|
func getMemoryUsage(stats []*info.ContainerStats) string {
|
||||||
return strconv.FormatFloat(toMegabytes((stats[len(stats)-1].Memory.Usage)), 'f', 2, 64)
|
return strconv.FormatFloat(toMegabytes((stats[len(stats)-1].Memory.Usage)), 'f', 2, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMemoryUsagePercent(spec *info.ContainerSpec, stats []*info.ContainerStats) int {
|
func getMemoryUsagePercent(spec *info.ContainerSpec, stats []*info.ContainerStats, machine *info.MachineInfo) int {
|
||||||
return toMemoryPercent((stats[len(stats)-1].Memory.Usage), spec)
|
return toMemoryPercent((stats[len(stats)-1].Memory.Usage), spec, machine)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHotMemoryPercent(spec *info.ContainerSpec, stats []*info.ContainerStats) int {
|
func getHotMemoryPercent(spec *info.ContainerSpec, stats []*info.ContainerStats, machine *info.MachineInfo) int {
|
||||||
return toMemoryPercent((stats[len(stats)-1].Memory.WorkingSet), spec)
|
return toMemoryPercent((stats[len(stats)-1].Memory.WorkingSet), spec, machine)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getColdMemoryPercent(spec *info.ContainerSpec, stats []*info.ContainerStats) int {
|
func getColdMemoryPercent(spec *info.ContainerSpec, stats []*info.ContainerStats, machine *info.MachineInfo) int {
|
||||||
latestStats := stats[len(stats)-1].Memory
|
latestStats := stats[len(stats)-1].Memory
|
||||||
return toMemoryPercent((latestStats.Usage)-(latestStats.WorkingSet), spec)
|
return toMemoryPercent((latestStats.Usage)-(latestStats.WorkingSet), spec, machine)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
|
func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
|
||||||
|
@ -132,16 +132,16 @@ const containersHtmlTemplate = `
|
|||||||
<h4>Usage Breakdown</h4>
|
<h4>Usage Breakdown</h4>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
<div class="progress-bar progress-bar-danger" style="width: {{getHotMemoryPercent .Spec .Stats}}%">
|
<div class="progress-bar progress-bar-danger" style="width: {{getHotMemoryPercent .Spec .Stats .MachineInfo}}%">
|
||||||
<span class="sr-only">Hot Memory</span>
|
<span class="sr-only">Hot Memory</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-bar progress-bar-info" style="width: {{getColdMemoryPercent .Spec .Stats}}%">
|
<div class="progress-bar progress-bar-info" style="width: {{getColdMemoryPercent .Spec .Stats .MachineInfo}}%">
|
||||||
<span class="sr-only">Cold Memory</span>
|
<span class="sr-only">Cold Memory</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
{{ getMemoryUsage .Stats }} MB ({{ getMemoryUsagePercent .Spec .Stats }}%)
|
{{ getMemoryUsage .Stats }} MB ({{ getMemoryUsagePercent .Spec .Stats .MachineInfo}}%)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h4>Page Faults</h4>
|
<h4>Page Faults</h4>
|
||||||
|
@ -154,7 +154,7 @@ function drawCpuUsageBreakdown(elementId, containerInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw the gauges for overall resource usage.
|
// Draw the gauges for overall resource usage.
|
||||||
function drawOverallUsage(elementId, containerInfo) {
|
function drawOverallUsage(elementId, machineInfo, containerInfo) {
|
||||||
var cur = containerInfo.stats[containerInfo.stats.length - 1];
|
var cur = containerInfo.stats[containerInfo.stats.length - 1];
|
||||||
|
|
||||||
var cpuUsage = 0;
|
var cpuUsage = 0;
|
||||||
@ -171,7 +171,13 @@ function drawOverallUsage(elementId, containerInfo) {
|
|||||||
|
|
||||||
var memoryUsage = 0;
|
var memoryUsage = 0;
|
||||||
if (containerInfo.spec.memory) {
|
if (containerInfo.spec.memory) {
|
||||||
memoryUsage = Math.round((cur.memory.usage / containerInfo.spec.memory.limit) * 100);
|
// Saturate to the machine size.
|
||||||
|
var limit = containerInfo.spec.memory.limit;
|
||||||
|
if (limit > machineInfo.memory_capacity) {
|
||||||
|
limit = machineInfo.memory_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryUsage = Math.round((cur.memory.usage / limit) * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawGauge(elementId, cpuUsage, memoryUsage);
|
drawGauge(elementId, cpuUsage, memoryUsage);
|
||||||
@ -236,7 +242,7 @@ function drawCharts(machineInfo, containerInfo) {
|
|||||||
var steps = [];
|
var steps = [];
|
||||||
|
|
||||||
steps.push(function() {
|
steps.push(function() {
|
||||||
drawOverallUsage("usage-gauge", containerInfo)
|
drawOverallUsage("usage-gauge", machineInfo, containerInfo)
|
||||||
});
|
});
|
||||||
|
|
||||||
// CPU.
|
// CPU.
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 sampling
|
package sampling
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 sampling
|
package sampling
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
Loading…
Reference in New Issue
Block a user