updated cadvisor godeps

This commit is contained in:
David Ashpole 2016-10-21 17:30:27 -07:00
parent 0006d6611e
commit aa20c4b48f
9 changed files with 248 additions and 148 deletions

165
Godeps/Godeps.json generated
View File

@ -1118,203 +1118,208 @@
}, },
{ {
"ImportPath": "github.com/google/cadvisor/api", "ImportPath": "github.com/google/cadvisor/api",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/cache/memory", "ImportPath": "github.com/google/cadvisor/cache/memory",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/client/v2", "ImportPath": "github.com/google/cadvisor/client/v2",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/collector", "ImportPath": "github.com/google/cadvisor/collector",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container", "ImportPath": "github.com/google/cadvisor/container",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/common", "ImportPath": "github.com/google/cadvisor/container/common",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/docker", "ImportPath": "github.com/google/cadvisor/container/docker",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/libcontainer", "ImportPath": "github.com/google/cadvisor/container/libcontainer",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/raw", "ImportPath": "github.com/google/cadvisor/container/raw",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/rkt", "ImportPath": "github.com/google/cadvisor/container/rkt",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/systemd", "ImportPath": "github.com/google/cadvisor/container/systemd",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/devicemapper", "ImportPath": "github.com/google/cadvisor/devicemapper",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/events", "ImportPath": "github.com/google/cadvisor/events",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/fs", "ImportPath": "github.com/google/cadvisor/fs",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/healthz", "ImportPath": "github.com/google/cadvisor/healthz",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/http", "ImportPath": "github.com/google/cadvisor/http",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/http/mux", "ImportPath": "github.com/google/cadvisor/http/mux",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v1", "ImportPath": "github.com/google/cadvisor/info/v1",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
},
{
"ImportPath": "github.com/google/cadvisor/info/v1/test",
"Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v2", "ImportPath": "github.com/google/cadvisor/info/v2",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/machine", "ImportPath": "github.com/google/cadvisor/machine",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager", "ImportPath": "github.com/google/cadvisor/manager",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher", "ImportPath": "github.com/google/cadvisor/manager/watcher",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw", "ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt", "ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/metrics", "ImportPath": "github.com/google/cadvisor/metrics",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/pages", "ImportPath": "github.com/google/cadvisor/pages",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/pages/static", "ImportPath": "github.com/google/cadvisor/pages/static",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/storage", "ImportPath": "github.com/google/cadvisor/storage",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/summary", "ImportPath": "github.com/google/cadvisor/summary",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils", "ImportPath": "github.com/google/cadvisor/utils",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo", "ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload", "ImportPath": "github.com/google/cadvisor/utils/cpuload",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink", "ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/docker", "ImportPath": "github.com/google/cadvisor/utils/docker",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/oomparser", "ImportPath": "github.com/google/cadvisor/utils/oomparser",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysfs", "ImportPath": "github.com/google/cadvisor/utils/sysfs",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysinfo", "ImportPath": "github.com/google/cadvisor/utils/sysinfo",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/tail", "ImportPath": "github.com/google/cadvisor/utils/tail",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/validate", "ImportPath": "github.com/google/cadvisor/validate",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/version", "ImportPath": "github.com/google/cadvisor/version",
"Comment": "v0.24.0-alpha1-39-ga9b1ab1", "Comment": "v0.24.0-alpha1-56-ga726d13",
"Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2" "Rev": "a726d13de8cb32860e73d72a78dc8e0124267709"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go", "ImportPath": "github.com/google/certificate-transparency/go",

View File

@ -16,6 +16,7 @@
package common package common
import ( import (
"fmt"
"sync" "sync"
"time" "time"
@ -26,71 +27,85 @@ import (
type FsHandler interface { type FsHandler interface {
Start() Start()
Usage() (baseUsageBytes uint64, totalUsageBytes uint64) Usage() FsUsage
Stop() Stop()
} }
type FsUsage struct {
BaseUsageBytes uint64
TotalUsageBytes uint64
InodeUsage uint64
}
type realFsHandler struct { type realFsHandler struct {
sync.RWMutex sync.RWMutex
lastUpdate time.Time lastUpdate time.Time
usageBytes uint64 usage FsUsage
baseUsageBytes uint64 period time.Duration
period time.Duration minPeriod time.Duration
minPeriod time.Duration rootfs string
rootfs string extraDir string
extraDir string fsInfo fs.FsInfo
fsInfo fs.FsInfo
// Tells the container to stop. // Tells the container to stop.
stopChan chan struct{} stopChan chan struct{}
} }
const ( const (
longDu = time.Second longOp = time.Second
duTimeout = time.Minute timeout = 2 * time.Minute
maxDuBackoffFactor = 20 maxBackoffFactor = 20
) )
const DefaultPeriod = time.Minute
var _ FsHandler = &realFsHandler{} var _ FsHandler = &realFsHandler{}
func NewFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) FsHandler { func NewFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) FsHandler {
return &realFsHandler{ return &realFsHandler{
lastUpdate: time.Time{}, lastUpdate: time.Time{},
usageBytes: 0, usage: FsUsage{},
baseUsageBytes: 0, period: period,
period: period, minPeriod: period,
minPeriod: period, rootfs: rootfs,
rootfs: rootfs, extraDir: extraDir,
extraDir: extraDir, fsInfo: fsInfo,
fsInfo: fsInfo, stopChan: make(chan struct{}, 1),
stopChan: make(chan struct{}, 1),
} }
} }
func (fh *realFsHandler) update() error { func (fh *realFsHandler) update() error {
var ( var (
baseUsage, extraDirUsage uint64 baseUsage, extraDirUsage, inodeUsage uint64
err error rootDiskErr, rootInodeErr, extraDiskErr error
) )
// TODO(vishh): Add support for external mounts. // TODO(vishh): Add support for external mounts.
if fh.rootfs != "" { if fh.rootfs != "" {
baseUsage, err = fh.fsInfo.GetDirUsage(fh.rootfs, duTimeout) baseUsage, rootDiskErr = fh.fsInfo.GetDirDiskUsage(fh.rootfs, timeout)
if err != nil { inodeUsage, rootInodeErr = fh.fsInfo.GetDirInodeUsage(fh.rootfs, timeout)
return err
}
} }
if fh.extraDir != "" { if fh.extraDir != "" {
extraDirUsage, err = fh.fsInfo.GetDirUsage(fh.extraDir, duTimeout) extraDirUsage, extraDiskErr = fh.fsInfo.GetDirDiskUsage(fh.extraDir, timeout)
if err != nil {
return err
}
} }
// Wait to handle errors until after all operartions are run.
// An error in one will not cause an early return, skipping others
fh.Lock() fh.Lock()
defer fh.Unlock() defer fh.Unlock()
fh.lastUpdate = time.Now() fh.lastUpdate = time.Now()
fh.usageBytes = baseUsage + extraDirUsage if rootDiskErr == nil && fh.rootfs != "" {
fh.baseUsageBytes = baseUsage fh.usage.InodeUsage = inodeUsage
}
if rootInodeErr == nil && fh.rootfs != "" {
fh.usage.TotalUsageBytes = baseUsage + extraDirUsage
}
if extraDiskErr == nil && fh.extraDir != "" {
fh.usage.BaseUsageBytes = baseUsage
}
// Combine errors into a single error to return
if rootDiskErr != nil || rootInodeErr != nil || extraDiskErr != nil {
return fmt.Errorf("rootDiskErr: %v, rootInodeErr: %v, extraDiskErr: %v", rootDiskErr, rootInodeErr, extraDiskErr)
}
return nil return nil
} }
@ -105,15 +120,15 @@ func (fh *realFsHandler) trackUsage() {
if err := fh.update(); err != nil { if err := fh.update(); err != nil {
glog.Errorf("failed to collect filesystem stats - %v", err) glog.Errorf("failed to collect filesystem stats - %v", err)
fh.period = fh.period * 2 fh.period = fh.period * 2
if fh.period > maxDuBackoffFactor*fh.minPeriod { if fh.period > maxBackoffFactor*fh.minPeriod {
fh.period = maxDuBackoffFactor * fh.minPeriod fh.period = maxBackoffFactor * fh.minPeriod
} }
} else { } else {
fh.period = fh.minPeriod fh.period = fh.minPeriod
} }
duration := time.Since(start) duration := time.Since(start)
if duration > longDu { if duration > longOp {
glog.V(2).Infof("`du` on following dirs took %v: %v", duration, []string{fh.rootfs, fh.extraDir}) glog.V(2).Infof("du and find on following dirs took %v: %v", duration, []string{fh.rootfs, fh.extraDir})
} }
} }
} }
@ -127,8 +142,8 @@ func (fh *realFsHandler) Stop() {
close(fh.stopChan) close(fh.stopChan)
} }
func (fh *realFsHandler) Usage() (baseUsageBytes, totalUsageBytes uint64) { func (fh *realFsHandler) Usage() FsUsage {
fh.RLock() fh.RLock()
defer fh.RUnlock() defer fh.RUnlock()
return fh.baseUsageBytes, fh.usageBytes return fh.usage
} }

View File

@ -243,7 +243,7 @@ func newDockerContainerHandler(
if !ignoreMetrics.Has(container.DiskUsageMetrics) { if !ignoreMetrics.Has(container.DiskUsageMetrics) {
handler.fsHandler = &dockerFsHandler{ handler.fsHandler = &dockerFsHandler{
fsHandler: common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo), fsHandler: common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, otherStorageDir, fsInfo),
thinPoolWatcher: thinPoolWatcher, thinPoolWatcher: thinPoolWatcher,
deviceID: handler.deviceID, deviceID: handler.deviceID,
} }
@ -283,8 +283,8 @@ func (h *dockerFsHandler) Stop() {
h.fsHandler.Stop() h.fsHandler.Stop()
} }
func (h *dockerFsHandler) Usage() (uint64, uint64) { func (h *dockerFsHandler) Usage() common.FsUsage {
baseUsage, usage := h.fsHandler.Usage() usage := h.fsHandler.Usage()
// When devicemapper is the storage driver, the base usage of the container comes from the thin pool. // When devicemapper is the storage driver, the base usage of the container comes from the thin pool.
// We still need the result of the fsHandler for any extra storage associated with the container. // We still need the result of the fsHandler for any extra storage associated with the container.
@ -299,12 +299,12 @@ func (h *dockerFsHandler) Usage() (uint64, uint64) {
// had at least 1 refresh and we still can't find the device. // had at least 1 refresh and we still can't find the device.
glog.V(5).Infof("unable to get fs usage from thin pool for device %s: %v", h.deviceID, err) glog.V(5).Infof("unable to get fs usage from thin pool for device %s: %v", h.deviceID, err)
} else { } else {
baseUsage = thinPoolUsage usage.BaseUsageBytes = thinPoolUsage
usage += thinPoolUsage usage.TotalUsageBytes += thinPoolUsage
} }
} }
return baseUsage, usage return usage
} }
func (self *dockerContainerHandler) Start() { func (self *dockerContainerHandler) Start() {
@ -387,7 +387,10 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error
} }
fsStat := info.FsStats{Device: device, Type: fsType, Limit: limit} fsStat := info.FsStats{Device: device, Type: fsType, Limit: limit}
fsStat.BaseUsage, fsStat.Usage = self.fsHandler.Usage() usage := self.fsHandler.Usage()
fsStat.BaseUsage = usage.BaseUsageBytes
fsStat.Usage = usage.TotalUsageBytes
fsStat.Inodes = usage.InodeUsage
stats.Filesystem = append(stats.Filesystem, fsStat) stats.Filesystem = append(stats.Filesystem, fsStat)

View File

@ -18,7 +18,6 @@ package rkt
import ( import (
"fmt" "fmt"
"os" "os"
"time"
rktapi "github.com/coreos/rkt/api/v1alpha" rktapi "github.com/coreos/rkt/api/v1alpha"
"github.com/google/cadvisor/container" "github.com/google/cadvisor/container"
@ -150,7 +149,7 @@ func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPa
} }
if !ignoreMetrics.Has(container.DiskUsageMetrics) { if !ignoreMetrics.Has(container.DiskUsageMetrics) {
handler.fsHandler = common.NewFsHandler(time.Minute, rootfsStorageDir, "", fsInfo) handler.fsHandler = common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, "", fsInfo)
} }
return handler, nil return handler, nil
@ -228,7 +227,10 @@ func (handler *rktContainerHandler) getFsStats(stats *info.ContainerStats) error
fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit} fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit}
fsStat.BaseUsage, fsStat.Usage = handler.fsHandler.Usage() usage := handler.fsHandler.Usage()
fsStat.BaseUsage = usage.BaseUsageBytes
fsStat.Usage = usage.TotalUsageBytes
fsStat.Inodes = usage.InodeUsage
stats.Filesystem = append(stats.Filesystem, fsStat) stats.Filesystem = append(stats.Filesystem, fsStat)

View File

@ -19,6 +19,7 @@ package fs
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -44,24 +45,24 @@ const (
LabelRktImages = "rkt-images" LabelRktImages = "rkt-images"
) )
// The maximum number of `du` tasks that can be running at once. // The maximum number of `du` and `find` tasks that can be running at once.
const maxConsecutiveDus = 20 const maxConcurrentOps = 20
// A pool for restricting the number of consecutive `du` tasks running. // A pool for restricting the number of consecutive `du` and `find` tasks running.
var duPool = make(chan struct{}, maxConsecutiveDus) var pool = make(chan struct{}, maxConcurrentOps)
func init() { func init() {
for i := 0; i < maxConsecutiveDus; i++ { for i := 0; i < maxConcurrentOps; i++ {
releaseDuToken() releaseToken()
} }
} }
func claimDuToken() { func claimToken() {
<-duPool <-pool
} }
func releaseDuToken() { func releaseToken() {
duPool <- struct{}{} pool <- struct{}{}
} }
type partition struct { type partition struct {
@ -428,12 +429,12 @@ func (self *RealFsInfo) GetDirFsDevice(dir string) (*DeviceInfo, error) {
return nil, fmt.Errorf("could not find device with major: %d, minor: %d in cached partitions map", major, minor) return nil, fmt.Errorf("could not find device with major: %d, minor: %d in cached partitions map", major, minor)
} }
func (self *RealFsInfo) GetDirUsage(dir string, timeout time.Duration) (uint64, error) { func (self *RealFsInfo) GetDirDiskUsage(dir string, timeout time.Duration) (uint64, error) {
if dir == "" { if dir == "" {
return 0, fmt.Errorf("invalid directory") return 0, fmt.Errorf("invalid directory")
} }
claimDuToken() claimToken()
defer releaseDuToken() defer releaseToken()
cmd := exec.Command("nice", "-n", "19", "du", "-s", dir) cmd := exec.Command("nice", "-n", "19", "du", "-s", dir)
stdoutp, err := cmd.StdoutPipe() stdoutp, err := cmd.StdoutPipe()
if err != nil { if err != nil {
@ -447,21 +448,21 @@ func (self *RealFsInfo) GetDirUsage(dir string, timeout time.Duration) (uint64,
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec du - %v", err) return 0, fmt.Errorf("failed to exec du - %v", err)
} }
stdoutb, souterr := ioutil.ReadAll(stdoutp)
stderrb, _ := ioutil.ReadAll(stderrp)
timer := time.AfterFunc(timeout, func() { timer := time.AfterFunc(timeout, func() {
glog.Infof("killing cmd %v due to timeout(%s)", cmd.Args, timeout.String()) glog.Infof("killing cmd %v due to timeout(%s)", cmd.Args, timeout.String())
cmd.Process.Kill() cmd.Process.Kill()
}) })
stdoutb, souterr := ioutil.ReadAll(stdoutp)
if souterr != nil {
glog.Errorf("failed to read from stdout for cmd %v - %v", cmd.Args, souterr)
}
stderrb, _ := ioutil.ReadAll(stderrp)
err = cmd.Wait() err = cmd.Wait()
timer.Stop() timer.Stop()
if err != nil { if err != nil {
return 0, fmt.Errorf("du command failed on %s with output stdout: %s, stderr: %s - %v", dir, string(stdoutb), string(stderrb), err) return 0, fmt.Errorf("du command failed on %s with output stdout: %s, stderr: %s - %v", dir, string(stdoutb), string(stderrb), err)
} }
stdout := string(stdoutb) stdout := string(stdoutb)
if souterr != nil {
glog.Errorf("failed to read from stdout for cmd %v - %v", cmd.Args, souterr)
}
usageInKb, err := strconv.ParseUint(strings.Fields(stdout)[0], 10, 64) usageInKb, err := strconv.ParseUint(strings.Fields(stdout)[0], 10, 64)
if err != nil { if err != nil {
return 0, fmt.Errorf("cannot parse 'du' output %s - %s", stdout, err) return 0, fmt.Errorf("cannot parse 'du' output %s - %s", stdout, err)
@ -469,6 +470,48 @@ func (self *RealFsInfo) GetDirUsage(dir string, timeout time.Duration) (uint64,
return usageInKb * 1024, nil return usageInKb * 1024, nil
} }
func (self *RealFsInfo) GetDirInodeUsage(dir string, timeout time.Duration) (uint64, error) {
if dir == "" {
return 0, fmt.Errorf("invalid directory")
}
var stdout, stdwcerr, stdfinderr bytes.Buffer
var err error
claimToken()
defer releaseToken()
findCmd := exec.Command("find", dir, "-xdev", "-printf", ".")
wcCmd := exec.Command("wc", "-c")
if wcCmd.Stdin, err = findCmd.StdoutPipe(); err != nil {
return 0, fmt.Errorf("failed to setup stdout for cmd %v - %v", findCmd.Args, err)
}
wcCmd.Stdout, wcCmd.Stderr, findCmd.Stderr = &stdout, &stdwcerr, &stdfinderr
if err = findCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr: %v", findCmd.Args, err, stdfinderr.String())
}
if err = wcCmd.Start(); err != nil {
return 0, fmt.Errorf("failed to exec cmd %v - %v; stderr %v", wcCmd.Args, err, stdwcerr.String())
}
timer := time.AfterFunc(timeout, func() {
glog.Infof("killing cmd %v, and cmd %v due to timeout(%s)", findCmd.Args, wcCmd.Args, timeout.String())
wcCmd.Process.Kill()
findCmd.Process.Kill()
})
err = findCmd.Wait()
if err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", findCmd.Args, stdfinderr.String(), err)
}
err = wcCmd.Wait()
if err != nil {
return 0, fmt.Errorf("cmd %v failed. stderr: %s; err: %v", wcCmd.Args, stdwcerr.String(), err)
}
timer.Stop()
inodeUsage, err := strconv.ParseUint(strings.TrimSpace(stdout.String()), 10, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse cmds: %v, %v output %s - %s", findCmd.Args, wcCmd.Args, stdout.String(), err)
}
return inodeUsage, nil
}
func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes uint64, inodesFree uint64, err error) { func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes uint64, inodesFree uint64, err error) {
var s syscall.Statfs_t var s syscall.Statfs_t
if err = syscall.Statfs(path, &s); err != nil { if err = syscall.Statfs(path, &s); err != nil {

View File

@ -67,7 +67,10 @@ type FsInfo interface {
GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, error) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, error)
// Returns number of bytes occupied by 'dir'. // Returns number of bytes occupied by 'dir'.
GetDirUsage(dir string, timeout time.Duration) (uint64, error) GetDirDiskUsage(dir string, timeout time.Duration) (uint64, error)
// Returns number of inodes used by 'dir'.
GetDirInodeUsage(dir string, timeout time.Duration) (uint64, error)
// Returns the block device info of the filesystem on which 'dir' resides. // Returns the block device info of the filesystem on which 'dir' resides.
GetDirFsDevice(dir string) (*DeviceInfo, error) GetDirFsDevice(dir string) (*DeviceInfo, error)

View File

@ -301,4 +301,8 @@ type FilesystemStats struct {
TotalUsageBytes *uint64 `json:"totalUsageBytes,omitempty"` TotalUsageBytes *uint64 `json:"totalUsageBytes,omitempty"`
// Number of bytes consumed by a container through its root filesystem. // Number of bytes consumed by a container through its root filesystem.
BaseUsageBytes *uint64 `json:"baseUsageBytes,omitempty"` BaseUsageBytes *uint64 `json:"baseUsageBytes,omitempty"`
// Number of inodes used within the container's root filesystem.
// This only accounts for inodes that are shared across containers,
// and does not include inodes used in mounted directories.
InodeUsage *uint64 `json:"containter_inode_usage,omitempty"`
} }

View File

@ -127,6 +127,7 @@ func ContainerStatsFromV1(spec *v1.ContainerSpec, stats []*v1.ContainerStats) []
stat.Filesystem = &FilesystemStats{ stat.Filesystem = &FilesystemStats{
TotalUsageBytes: &val.Filesystem[0].Usage, TotalUsageBytes: &val.Filesystem[0].Usage,
BaseUsageBytes: &val.Filesystem[0].BaseUsage, BaseUsageBytes: &val.Filesystem[0].BaseUsage,
InodeUsage: &val.Filesystem[0].Inodes,
} }
} else if len(val.Filesystem) > 1 { } else if len(val.Filesystem) > 1 {
// Cannot handle multiple devices per container. // Cannot handle multiple devices per container.

View File

@ -101,6 +101,9 @@ type Manager interface {
// Get version information about different components we depend on. // Get version information about different components we depend on.
GetVersionInfo() (*info.VersionInfo, error) GetVersionInfo() (*info.VersionInfo, error)
// Get filesystem information for the filesystem that contains the given directory
GetDirFsInfo(dir string) (v2.FsInfo, error)
// Get filesystem information for a given label. // Get filesystem information for a given label.
// Returns information for all global filesystems if label is empty. // Returns information for all global filesystems if label is empty.
GetFsInfo(label string) ([]v2.FsInfo, error) GetFsInfo(label string) ([]v2.FsInfo, error)
@ -657,6 +660,27 @@ func (self *manager) getRequestedContainers(containerName string, options v2.Req
return containersMap, nil return containersMap, nil
} }
func (self *manager) GetDirFsInfo(dir string) (v2.FsInfo, error) {
dirDevice, err := self.fsInfo.GetDirFsDevice(dir)
if err != nil {
return v2.FsInfo{}, fmt.Errorf("error trying to get filesystem Device for dir %v: err: %v", dir, err)
}
dirMountpoint, err := self.fsInfo.GetMountpointForDevice(dirDevice.Device)
if err != nil {
return v2.FsInfo{}, fmt.Errorf("error trying to get MountPoint for Root Device: %v, err: %v", dirDevice, err)
}
infos, err := self.GetFsInfo("")
if err != nil {
return v2.FsInfo{}, err
}
for _, info := range infos {
if info.Mountpoint == dirMountpoint {
return info, nil
}
}
return v2.FsInfo{}, fmt.Errorf("did not find fs info for dir: %v", dir)
}
func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) { func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) {
var empty time.Time var empty time.Time
// Get latest data from filesystems hanging off root container. // Get latest data from filesystems hanging off root container.