updating cadvisor deps

Signed-off-by: Vishnu kannan <vishnuk@google.com>
This commit is contained in:
Vishnu kannan
2016-07-19 17:20:25 -07:00
parent a0a0760027
commit cdeaef2c05
122 changed files with 6209 additions and 2355 deletions

View File

@@ -17,12 +17,13 @@ package collector
import (
"time"
"encoding/json"
"github.com/google/cadvisor/info/v1"
)
type Config struct {
//the endpoint to hit to scrape metrics
Endpoint string `json:"endpoint"`
Endpoint EndpointConfig `json:"endpoint"`
//holds information about different metrics that can be collected
MetricsConfig []MetricConfig `json:"metrics_config"`
@@ -52,7 +53,7 @@ type MetricConfig struct {
type Prometheus struct {
//the endpoint to hit to scrape metrics
Endpoint string `json:"endpoint"`
Endpoint EndpointConfig `json:"endpoint"`
//the frequency at which metrics should be collected
PollingFrequency time.Duration `json:"polling_frequency"`
@@ -60,3 +61,40 @@ type Prometheus struct {
//holds names of different metrics that can be collected
MetricsConfig []string `json:"metrics_config"`
}
type EndpointConfig struct {
// The full URL of the endpoint to reach
URL string
// A configuration in which an actual URL is constructed from, using the container's ip address
URLConfig URLConfig
}
type URLConfig struct {
// the protocol to use for connecting to the endpoint. Eg 'http' or 'https'
Protocol string `json:"protocol"`
// the port to use for connecting to the endpoint. Eg '8778'
Port json.Number `json:"port"`
// the path to use for the endpoint. Eg '/metrics'
Path string `json:"path"`
}
func (ec *EndpointConfig) UnmarshalJSON(b []byte) error {
url := ""
config := URLConfig{
Protocol: "http",
Port: "8000",
}
if err := json.Unmarshal(b, &url); err == nil {
ec.URL = url
return nil
}
err := json.Unmarshal(b, &config)
if err == nil {
ec.URLConfig = config
return nil
}
return err
}

View File

@@ -24,6 +24,7 @@ import (
"strings"
"time"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/info/v1"
)
@@ -51,13 +52,15 @@ type collectorInfo struct {
}
//Returns a new collector using the information extracted from the configfile
func NewCollector(collectorName string, configFile []byte, metricCountLimit int) (*GenericCollector, error) {
func NewCollector(collectorName string, configFile []byte, metricCountLimit int, containerHandler container.ContainerHandler) (*GenericCollector, error) {
var configInJSON Config
err := json.Unmarshal(configFile, &configInJSON)
if err != nil {
return nil, err
}
configInJSON.Endpoint.configure(containerHandler)
//TODO : Add checks for validity of config file (eg : Accurate JSON fields)
if len(configInJSON.MetricsConfig) == 0 {
@@ -130,7 +133,7 @@ func (collector *GenericCollector) Collect(metrics map[string][]v1.MetricVal) (t
currentTime := time.Now()
nextCollectionTime := currentTime.Add(time.Duration(collector.info.minPollingFrequency))
uri := collector.configFile.Endpoint
uri := collector.configFile.Endpoint.URL
response, err := http.Get(uri)
if err != nil {
return nextCollectionTime, nil, err

View File

@@ -24,6 +24,7 @@ import (
"strings"
"time"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/info/v1"
)
@@ -46,13 +47,15 @@ type PrometheusCollector struct {
}
//Returns a new collector using the information extracted from the configfile
func NewPrometheusCollector(collectorName string, configFile []byte, metricCountLimit int) (*PrometheusCollector, error) {
func NewPrometheusCollector(collectorName string, configFile []byte, metricCountLimit int, containerHandler container.ContainerHandler) (*PrometheusCollector, error) {
var configInJSON Prometheus
err := json.Unmarshal(configFile, &configInJSON)
if err != nil {
return nil, err
}
configInJSON.Endpoint.configure(containerHandler)
minPollingFrequency := configInJSON.PollingFrequency
// Minimum supported frequency is 1s
@@ -108,7 +111,7 @@ func getMetricData(line string) string {
func (collector *PrometheusCollector) GetSpec() []v1.MetricSpec {
specs := []v1.MetricSpec{}
response, err := http.Get(collector.configFile.Endpoint)
response, err := http.Get(collector.configFile.Endpoint.URL)
if err != nil {
return specs
}
@@ -153,7 +156,7 @@ func (collector *PrometheusCollector) Collect(metrics map[string][]v1.MetricVal)
currentTime := time.Now()
nextCollectionTime := currentTime.Add(time.Duration(collector.pollingFrequency))
uri := collector.configFile.Endpoint
uri := collector.configFile.Endpoint.URL
response, err := http.Get(uri)
if err != nil {
return nextCollectionTime, nil, err

26
vendor/github.com/google/cadvisor/collector/util.go generated vendored Normal file
View File

@@ -0,0 +1,26 @@
// Copyright 2016 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 collector
import "github.com/google/cadvisor/container"
func (endpointConfig *EndpointConfig) configure(containerHandler container.ContainerHandler) {
//If the exact URL was not specified, generate it based on the ip address of the container.
endpoint := endpointConfig
if endpoint.URL == "" {
ipAddress := containerHandler.GetContainerIPAddress()
endpointConfig.URL = endpoint.URLConfig.Protocol + "://" + ipAddress + ":" + endpoint.URLConfig.Port.String() + endpoint.URLConfig.Path
}
}

View File

@@ -59,6 +59,9 @@ type ContainerHandler interface {
// Returns container labels, if available.
GetContainerLabels() map[string]string
// Returns the container's ip address, if available
GetContainerIPAddress() string
// Returns whether the container still exists.
Exists() bool

View File

@@ -94,6 +94,9 @@ type dockerContainerHandler struct {
// Filesystem handler.
fsHandler common.FsHandler
// The IP address of the container
ipAddress string
ignoreMetrics container.MetricSet
// thin pool watcher
@@ -222,6 +225,22 @@ func newDockerContainerHandler(
handler.networkMode = ctnr.HostConfig.NetworkMode
handler.deviceID = ctnr.GraphDriver.Data["DeviceId"]
// Obtain the IP address for the contianer.
// If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified.
// This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address
ipAddress := ctnr.NetworkSettings.IPAddress
networkMode := string(ctnr.HostConfig.NetworkMode)
if ipAddress == "" && strings.HasPrefix(networkMode, "container:") {
containerId := strings.TrimPrefix(networkMode, "container:")
c, err := client.ContainerInspect(context.Background(), containerId)
if err != nil {
return nil, fmt.Errorf("failed to inspect container %q: %v", id, err)
}
ipAddress = c.NetworkSettings.IPAddress
}
handler.ipAddress = ipAddress
if !ignoreMetrics.Has(container.DiskUsageMetrics) {
handler.fsHandler = &dockerFsHandler{
fsHandler: common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo),
@@ -412,6 +431,10 @@ func (self *dockerContainerHandler) GetContainerLabels() map[string]string {
return self.labels
}
func (self *dockerContainerHandler) GetContainerIPAddress() string {
return self.ipAddress
}
func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
return containerlibcontainer.GetProcesses(self.cgroupManager)
}

View File

@@ -387,23 +387,16 @@ func toContainerStats2(s *cgroups.Stats, ret *info.ContainerStats) {
ret.Memory.ContainerData.Pgmajfault = v
ret.Memory.HierarchicalData.Pgmajfault = v
}
if v, ok := s.MemoryStats.Stats["total_inactive_anon"]; ok {
workingSet := ret.Memory.Usage
workingSet := ret.Memory.Usage
if v, ok := s.MemoryStats.Stats["total_inactive_file"]; ok {
if workingSet < v {
workingSet = 0
} else {
workingSet -= v
}
if v, ok := s.MemoryStats.Stats["total_inactive_file"]; ok {
if workingSet < v {
workingSet = 0
} else {
workingSet -= v
}
}
ret.Memory.WorkingSet = workingSet
}
ret.Memory.WorkingSet = workingSet
}
func toContainerStats3(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) {

View File

@@ -1,119 +0,0 @@
// 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.
// +build test
package container
import (
info "github.com/google/cadvisor/info/v1"
"github.com/stretchr/testify/mock"
)
// This struct mocks a container handler.
type MockContainerHandler struct {
mock.Mock
Name string
Aliases []string
}
func NewMockContainerHandler(containerName string) *MockContainerHandler {
return &MockContainerHandler{
Name: containerName,
}
}
// If self.Name is not empty, then ContainerReference() will return self.Name and self.Aliases.
// Otherwise, it will use the value provided by .On().Return().
func (self *MockContainerHandler) ContainerReference() (info.ContainerReference, error) {
if len(self.Name) > 0 {
var aliases []string
if len(self.Aliases) > 0 {
aliases = make([]string, len(self.Aliases))
copy(aliases, self.Aliases)
}
return info.ContainerReference{
Name: self.Name,
Aliases: aliases,
}, nil
}
args := self.Called()
return args.Get(0).(info.ContainerReference), args.Error(1)
}
func (self *MockContainerHandler) Start() {}
func (self *MockContainerHandler) Cleanup() {}
func (self *MockContainerHandler) GetSpec() (info.ContainerSpec, error) {
args := self.Called()
return args.Get(0).(info.ContainerSpec), args.Error(1)
}
func (self *MockContainerHandler) GetStats() (*info.ContainerStats, error) {
args := self.Called()
return args.Get(0).(*info.ContainerStats), args.Error(1)
}
func (self *MockContainerHandler) ListContainers(listType ListType) ([]info.ContainerReference, error) {
args := self.Called(listType)
return args.Get(0).([]info.ContainerReference), args.Error(1)
}
func (self *MockContainerHandler) ListProcesses(listType ListType) ([]int, error) {
args := self.Called(listType)
return args.Get(0).([]int), args.Error(1)
}
func (self *MockContainerHandler) Exists() bool {
args := self.Called()
return args.Get(0).(bool)
}
func (self *MockContainerHandler) GetCgroupPath(path string) (string, error) {
args := self.Called(path)
return args.Get(0).(string), args.Error(1)
}
func (self *MockContainerHandler) GetContainerLabels() map[string]string {
args := self.Called()
return args.Get(0).(map[string]string)
}
func (self *MockContainerHandler) Type() ContainerType {
args := self.Called()
return args.Get(0).(ContainerType)
}
type FactoryForMockContainerHandler struct {
Name string
PrepareContainerHandlerFunc func(name string, handler *MockContainerHandler)
}
func (self *FactoryForMockContainerHandler) String() string {
return self.Name
}
func (self *FactoryForMockContainerHandler) NewContainerHandler(name string, inHostNamespace bool) (ContainerHandler, error) {
handler := &MockContainerHandler{}
if self.PrepareContainerHandlerFunc != nil {
self.PrepareContainerHandlerFunc(name, handler)
}
return handler, nil
}
func (self *FactoryForMockContainerHandler) CanHandle(name string) bool {
return true
}

View File

@@ -256,6 +256,11 @@ func (self *rawContainerHandler) GetContainerLabels() map[string]string {
return map[string]string{}
}
func (self *rawContainerHandler) GetContainerIPAddress() string {
// the IP address for the raw container corresponds to the system ip address.
return "127.0.0.1"
}
func (self *rawContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
return common.ListContainers(self.name, self.cgroupPaths, listType)
}

View File

@@ -250,6 +250,21 @@ func (handler *rktContainerHandler) GetStats() (*info.ContainerStats, error) {
return stats, nil
}
func (self *rktContainerHandler) GetContainerIPAddress() string {
// attempt to return the ip address of the pod
// if a specific ip address of the pod could not be determined, return the system ip address
if self.isPod && len(self.apiPod.Networks) > 0 {
address := self.apiPod.Networks[0].Ipv4
if address != "" {
return address
} else {
return self.apiPod.Networks[0].Ipv6
}
} else {
return "127.0.0.1"
}
}
func (handler *rktContainerHandler) GetCgroupPath(resource string) (string, error) {
path, ok := handler.cgroupPaths[resource]
if !ok {

View File

@@ -80,7 +80,7 @@ func parseThinLsOutput(output []byte) map[string]uint64 {
deviceID := fields[0]
usage, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
glog.Warningf("unexpected error parsing thin_ls output: %v", err)
glog.Warning("unexpected error parsing thin_ls output: %v", err)
continue
}

View File

@@ -99,38 +99,15 @@ func NewFsInfo(context Context) (FsInfo, error) {
if err != nil {
return nil, err
}
// Avoid devicemapper container mounts - these are tracked by the ThinPoolWatcher
excluded := []string{fmt.Sprintf("%s/devicemapper/mnt", context.Docker.Root)}
fsInfo := &RealFsInfo{
partitions: make(map[string]partition, 0),
partitions: processMounts(mounts, excluded),
labels: make(map[string]string, 0),
dmsetup: devicemapper.NewDmsetupClient(),
}
supportedFsType := map[string]bool{
// all ext systems are checked through prefix.
"btrfs": true,
"xfs": true,
"zfs": true,
}
for _, mount := range mounts {
var Fstype string
if !strings.HasPrefix(mount.Fstype, "ext") && !supportedFsType[mount.Fstype] {
continue
}
// Avoid bind mounts.
if _, ok := fsInfo.partitions[mount.Source]; ok {
continue
}
if mount.Fstype == "zfs" {
Fstype = mount.Fstype
}
fsInfo.partitions[mount.Source] = partition{
fsType: Fstype,
mountpoint: mount.Mountpoint,
major: uint(mount.Major),
minor: uint(mount.Minor),
}
}
fsInfo.addRktImagesLabel(context, mounts)
// need to call this before the log line below printing out the partitions, as this function may
// add a "partition" for devicemapper to fsInfo.partitions
@@ -141,6 +118,47 @@ func NewFsInfo(context Context) (FsInfo, error) {
return fsInfo, nil
}
func processMounts(mounts []*mount.Info, excludedMountpointPrefixes []string) map[string]partition {
partitions := make(map[string]partition, 0)
supportedFsType := map[string]bool{
// all ext systems are checked through prefix.
"btrfs": true,
"xfs": true,
"zfs": true,
}
for _, mount := range mounts {
if !strings.HasPrefix(mount.Fstype, "ext") && !supportedFsType[mount.Fstype] {
continue
}
// Avoid bind mounts.
if _, ok := partitions[mount.Source]; ok {
continue
}
hasPrefix := false
for _, prefix := range excludedMountpointPrefixes {
if strings.HasPrefix(mount.Mountpoint, prefix) {
hasPrefix = true
break
}
}
if hasPrefix {
continue
}
partitions[mount.Source] = partition{
fsType: mount.Fstype,
mountpoint: mount.Mountpoint,
major: uint(mount.Major),
minor: uint(mount.Minor),
}
}
return partitions
}
// getDockerDeviceMapperInfo returns information about the devicemapper device and "partition" if
// docker is using devicemapper for its storage driver. If a loopback device is being used, don't
// return any information or error, as we want to report based on the actual partition where the

View File

@@ -752,7 +752,7 @@ func (m *manager) registerCollectors(collectorConfigs map[string]string, cont *c
glog.V(3).Infof("Got config from %q: %q", v, configFile)
if strings.HasPrefix(k, "prometheus") || strings.HasPrefix(k, "Prometheus") {
newCollector, err := collector.NewPrometheusCollector(k, configFile, *applicationMetricsCountLimit)
newCollector, err := collector.NewPrometheusCollector(k, configFile, *applicationMetricsCountLimit, cont.handler)
if err != nil {
glog.Infof("failed to create collector for container %q, config %q: %v", cont.info.Name, k, err)
return err
@@ -763,7 +763,7 @@ func (m *manager) registerCollectors(collectorConfigs map[string]string, cont *c
return err
}
} else {
newCollector, err := collector.NewCollector(k, configFile, *applicationMetricsCountLimit)
newCollector, err := collector.NewCollector(k, configFile, *applicationMetricsCountLimit, cont.handler)
if err != nil {
glog.Infof("failed to create collector for container %q, config %q: %v", cont.info.Name, k, err)
return err

View File

@@ -19,6 +19,7 @@ package raw
import (
"fmt"
"io/ioutil"
"os"
"path"
"strings"
@@ -133,9 +134,15 @@ func (self *rawContainerWatcher) watchDirectory(dir string, containerName string
}
for _, entry := range entries {
if entry.IsDir() {
// TODO(vmarmol): We don't have to fail here, maybe we can recover and try to get as many registrations as we can.
_, err = self.watchDirectory(path.Join(dir, entry.Name()), path.Join(containerName, entry.Name()))
entryPath := path.Join(dir, entry.Name())
_, err = self.watchDirectory(entryPath, path.Join(containerName, entry.Name()))
if err != nil {
glog.Errorf("Failed to watch directory %q: %v", entryPath, err)
if os.IsNotExist(err) {
// The directory may have been removed before watching. Try to watch the other
// subdirectories. (https://github.com/kubernetes/kubernetes/issues/28997)
continue
}
return alreadyWatching, err
}
}

View File

@@ -15,15 +15,27 @@
package cloudinfo
import (
"io/ioutil"
"strings"
info "github.com/google/cadvisor/info/v1"
"github.com/golang/glog"
"google.golang.org/cloud/compute/metadata"
)
const (
gceProductName = "/sys/class/dmi/id/product_name"
google = "Google"
)
func onGCE() bool {
return metadata.OnGCE()
data, err := ioutil.ReadFile(gceProductName)
if err != nil {
glog.V(2).Infof("Error while reading product_name: %v", err)
return false
}
return strings.Contains(string(data), google)
}
func getGceInstanceType() info.InstanceType {

View File

@@ -1 +0,0 @@
0.23.6