Allow partial success of GetStats().

This should make us more robust in the face of failure (at the cost of
making the failures less prominent). We allow GetStats() to return an
error and a partial result. We will process the result and report the
error.

Fixes #306.
This commit is contained in:
Victor Marmol 2015-02-03 15:26:31 -08:00
parent 01b456c129
commit 86238d0179
4 changed files with 16 additions and 11 deletions

View File

@ -82,6 +82,7 @@ func newDockerContainerHandler(
usesAufsDriver bool,
cgroupSubsystems *containerLibcontainer.CgroupSubsystems,
) (container.ContainerHandler, error) {
// TODO(vmarmol): Get from factory.
fsInfo, err := fs.NewFsInfo()
if err != nil {
return nil, err
@ -299,16 +300,16 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error
func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err error) {
state, err := self.readLibcontainerState()
if err != nil {
return
return nil, err
}
stats, err = containerLibcontainer.GetStats(self.cgroupPaths, state)
if err != nil {
return
return stats, err
}
err = self.getFsStats(stats)
if err != nil {
return
return stats, err
}
return stats, nil

View File

@ -76,6 +76,7 @@ func newRawContainerHandler(name string, cgroupSubsystems *libcontainer.CgroupSu
cgroupPaths[key] = path.Join(val, name)
}
// TODO(vmarmol): Get from factory.
fsInfo, err := fs.NewFsInfo()
if err != nil {
return nil, err
@ -303,12 +304,12 @@ func (self *rawContainerHandler) getFsStats(stats *info.ContainerStats) error {
func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) {
stats, err := libcontainer.GetStats(self.cgroupPaths, &self.libcontainerState)
if err != nil {
return nil, err
return stats, err
}
err = self.getFsStats(stats)
if err != nil {
return nil, err
return stats, err
}
// Fill in network stats for root.

View File

@ -67,6 +67,7 @@ func NewFsInfo() (FsInfo, error) {
}
partitions[mount.Source] = partition{mount.Mountpoint, uint(mount.Major), uint(mount.Minor)}
}
glog.Infof("Filesystem partitions: %+v", partitions)
return &RealFsInfo{partitions}, nil
}
@ -80,7 +81,7 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er
for device, partition := range self.partitions {
_, hasMount := mountSet[partition.mountpoint]
_, hasDevice := deviceSet[device]
if mountSet == nil || hasMount && !hasDevice {
if mountSet == nil || (hasMount && !hasDevice) {
total, free, err := getVfsStats(partition.mountpoint)
if err != nil {
glog.Errorf("Statvfs failed. Error: %v", err)

View File

@ -244,18 +244,20 @@ func (c *containerData) updateLoad(newLoad uint64) {
}
func (c *containerData) updateStats() error {
stats, err := c.handler.GetStats()
if err != nil {
stats, statsErr := c.handler.GetStats()
if statsErr != nil {
// Ignore errors if the container is dead.
if !c.handler.Exists() {
return nil
}
return err
// Stats may be partially populated, push those before we return an error.
}
if stats == nil {
return nil
return statsErr
}
if c.loadReader != nil {
// TODO(vmarmol): Cache this path.
path, err := c.handler.GetCgroupPath("cpu")
if err == nil {
loadStats, err := c.loadReader.GetCpuLoad(c.info.Name, path)
@ -280,7 +282,7 @@ func (c *containerData) updateStats() error {
if err != nil {
return err
}
return nil
return statsErr
}
func (c *containerData) updateSubcontainers() error {