mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Update Kubernetes cadvisor to pull in @b7bbefd9b1d4c1032c6afece425a99ba17e43cdb so that the VersionInfo is not cached.
This commit is contained in:
parent
3c0a05de4a
commit
dae4142d5c
76
Godeps/Godeps.json
generated
76
Godeps/Godeps.json
generated
@ -18,10 +18,6 @@
|
||||
"ImportPath": "code.google.com/p/gcfg",
|
||||
"Rev": "c2d3050044d05357eaf6c3547249ba57c5e235cb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/GoogleCloudPlatform/gcloud-golang/compute/metadata",
|
||||
"Rev": "e34a32f9b0ecbc0784865fb2d47f3818c09521d4"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Sirupsen/logrus",
|
||||
"Comment": "v0.6.2-10-g51fe59a",
|
||||
@ -269,93 +265,93 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/api",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/cache/memory",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/collector",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/container",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/events",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/fs",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/healthz",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/http",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/info/v1",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/info/v2",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/manager",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/metrics",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/pages",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/storage",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/summary",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/utils",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/validate",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/cadvisor/version",
|
||||
"Comment": "0.16.0-51-g78419de",
|
||||
"Rev": "78419de3ea9c2d23cb04ec9d63f8899de34ebd43"
|
||||
"Comment": "0.16.0-81-g27fb6d5",
|
||||
"Rev": "27fb6d593c6bffe274718119659815771e79e198"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/gofuzz",
|
||||
|
34
Godeps/_workspace/src/github.com/google/cadvisor/api/versions.go
generated
vendored
34
Godeps/_workspace/src/github.com/google/cadvisor/api/versions.go
generated
vendored
@ -372,19 +372,33 @@ func (self *version2_0) HandleRequest(requestType string, request []string, m ma
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
specs, err := m.GetContainerSpec(containerName, opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contMetrics := make(map[string]map[string][]info.MetricVal, 0)
|
||||
contMetrics := make(map[string]map[string]map[string][]info.MetricValBasic, 0)
|
||||
for _, cont := range conts {
|
||||
metrics := map[string][]info.MetricVal{}
|
||||
metrics := make(map[string]map[string][]info.MetricValBasic, 0)
|
||||
contStats := convertStats(cont)
|
||||
spec := specs[cont.Name]
|
||||
for _, contStat := range contStats {
|
||||
for _, ms := range spec.CustomMetrics {
|
||||
if contStat.HasCustomMetrics && !contStat.CustomMetrics[ms.Name].Timestamp.IsZero() {
|
||||
metrics[ms.Name] = append(metrics[ms.Name], contStat.CustomMetrics[ms.Name])
|
||||
if contStat.HasCustomMetrics {
|
||||
for name, allLabels := range contStat.CustomMetrics {
|
||||
metricLabels := make(map[string][]info.MetricValBasic, 0)
|
||||
for _, metric := range allLabels {
|
||||
if !metric.Timestamp.IsZero() {
|
||||
metVal := info.MetricValBasic{
|
||||
Timestamp: metric.Timestamp,
|
||||
IntValue: metric.IntValue,
|
||||
FloatValue: metric.FloatValue,
|
||||
}
|
||||
labels := metrics[name]
|
||||
if labels != nil {
|
||||
values := labels[metric.Label]
|
||||
values = append(values, metVal)
|
||||
labels[metric.Label] = values
|
||||
metrics[name] = labels
|
||||
} else {
|
||||
metricLabels[metric.Label] = []info.MetricValBasic{metVal}
|
||||
metrics[name] = metricLabels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager.go
generated
vendored
4
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager.go
generated
vendored
@ -71,12 +71,12 @@ func (cm *GenericCollectorManager) GetSpec() ([]v1.MetricSpec, error) {
|
||||
return metricSpec, nil
|
||||
}
|
||||
|
||||
func (cm *GenericCollectorManager) Collect() (time.Time, map[string]v1.MetricVal, error) {
|
||||
func (cm *GenericCollectorManager) Collect() (time.Time, map[string][]v1.MetricVal, error) {
|
||||
var errors []error
|
||||
|
||||
// Collect from all collectors that are ready.
|
||||
var next time.Time
|
||||
metrics := map[string]v1.MetricVal{}
|
||||
metrics := map[string][]v1.MetricVal{}
|
||||
for _, c := range cm.Collectors {
|
||||
if c.nextCollectionTime.Before(time.Now()) {
|
||||
var err error
|
||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager_test.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager_test.go
generated
vendored
@ -28,7 +28,7 @@ type fakeCollector struct {
|
||||
collectedFrom int
|
||||
}
|
||||
|
||||
func (fc *fakeCollector) Collect(metric map[string]v1.MetricVal) (time.Time, map[string]v1.MetricVal, error) {
|
||||
func (fc *fakeCollector) Collect(metric map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) {
|
||||
fc.collectedFrom++
|
||||
return fc.nextCollectionTime, metric, fc.err
|
||||
}
|
||||
|
11
Godeps/_workspace/src/github.com/google/cadvisor/collector/config.go
generated
vendored
11
Godeps/_workspace/src/github.com/google/cadvisor/collector/config.go
generated
vendored
@ -48,3 +48,14 @@ type MetricConfig struct {
|
||||
//the regular expression that can be used to extract the metric
|
||||
Regex string `json:"regex"`
|
||||
}
|
||||
|
||||
type Prometheus struct {
|
||||
//the endpoint to hit to scrape metrics
|
||||
Endpoint string `json:"endpoint"`
|
||||
|
||||
//the frequency at which metrics should be collected
|
||||
PollingFrequency time.Duration `json:"polling_frequency"`
|
||||
|
||||
//holds names of different metrics that can be collected
|
||||
MetricsConfig []string `json:"metrics_config"`
|
||||
}
|
||||
|
6
Godeps/_workspace/src/github.com/google/cadvisor/collector/config/sample_config_prometheus.json
generated
vendored
Normal file
6
Godeps/_workspace/src/github.com/google/cadvisor/collector/config/sample_config_prometheus.json
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"endpoint" : "http://localhost:8080/metrics",
|
||||
"polling_frequency" : 10,
|
||||
"metrics_config" : [
|
||||
]
|
||||
}
|
2
Godeps/_workspace/src/github.com/google/cadvisor/collector/fakes.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/collector/fakes.go
generated
vendored
@ -31,7 +31,7 @@ func (fkm *FakeCollectorManager) GetSpec() ([]v1.MetricSpec, error) {
|
||||
return []v1.MetricSpec{}, nil
|
||||
}
|
||||
|
||||
func (fkm *FakeCollectorManager) Collect(metric map[string]v1.MetricVal) (time.Time, map[string]v1.MetricVal, error) {
|
||||
func (fkm *FakeCollectorManager) Collect(metric map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) {
|
||||
var zero time.Time
|
||||
return zero, metric, nil
|
||||
}
|
||||
|
10
Godeps/_workspace/src/github.com/google/cadvisor/collector/generic_collector.go
generated
vendored
10
Godeps/_workspace/src/github.com/google/cadvisor/collector/generic_collector.go
generated
vendored
@ -116,7 +116,7 @@ func (collector *GenericCollector) GetSpec() []v1.MetricSpec {
|
||||
}
|
||||
|
||||
//Returns collected metrics and the next collection time of the collector
|
||||
func (collector *GenericCollector) Collect(metrics map[string]v1.MetricVal) (time.Time, map[string]v1.MetricVal, error) {
|
||||
func (collector *GenericCollector) Collect(metrics map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) {
|
||||
currentTime := time.Now()
|
||||
nextCollectionTime := currentTime.Add(time.Duration(collector.info.minPollingFrequency))
|
||||
|
||||
@ -142,16 +142,16 @@ func (collector *GenericCollector) Collect(metrics map[string]v1.MetricVal) (tim
|
||||
if err != nil {
|
||||
errorSlice = append(errorSlice, err)
|
||||
}
|
||||
metrics[metricConfig.Name] = v1.MetricVal{
|
||||
FloatValue: regVal, Timestamp: currentTime,
|
||||
metrics[metricConfig.Name] = []v1.MetricVal{
|
||||
{FloatValue: regVal, Timestamp: currentTime},
|
||||
}
|
||||
} else if metricConfig.DataType == v1.IntType {
|
||||
regVal, err := strconv.ParseInt(strings.TrimSpace(matchString[1]), 10, 64)
|
||||
if err != nil {
|
||||
errorSlice = append(errorSlice, err)
|
||||
}
|
||||
metrics[metricConfig.Name] = v1.MetricVal{
|
||||
IntValue: regVal, Timestamp: currentTime,
|
||||
metrics[metricConfig.Name] = []v1.MetricVal{
|
||||
{IntValue: regVal, Timestamp: currentTime},
|
||||
}
|
||||
|
||||
} else {
|
||||
|
18
Godeps/_workspace/src/github.com/google/cadvisor/collector/generic_collector_test.go
generated
vendored
18
Godeps/_workspace/src/github.com/google/cadvisor/collector/generic_collector_test.go
generated
vendored
@ -148,20 +148,20 @@ func TestMetricCollection(t *testing.T) {
|
||||
defer tempServer.Close()
|
||||
fakeCollector.configFile.Endpoint = tempServer.URL
|
||||
|
||||
metrics := map[string]v1.MetricVal{}
|
||||
metrics := map[string][]v1.MetricVal{}
|
||||
_, metrics, errMetric := fakeCollector.Collect(metrics)
|
||||
assert.NoError(errMetric)
|
||||
metricNames := []string{"activeConnections", "reading", "writing", "waiting"}
|
||||
// activeConnections = 3
|
||||
assert.Equal(metrics[metricNames[0]].IntValue, 3)
|
||||
assert.Equal(metrics[metricNames[0]].FloatValue, 0)
|
||||
assert.Equal(metrics[metricNames[0]][0].IntValue, 3)
|
||||
assert.Equal(metrics[metricNames[0]][0].FloatValue, 0)
|
||||
// reading = 0
|
||||
assert.Equal(metrics[metricNames[1]].IntValue, 0)
|
||||
assert.Equal(metrics[metricNames[1]].FloatValue, 0)
|
||||
assert.Equal(metrics[metricNames[1]][0].IntValue, 0)
|
||||
assert.Equal(metrics[metricNames[1]][0].FloatValue, 0)
|
||||
// writing = 1
|
||||
assert.Equal(metrics[metricNames[2]].IntValue, 1)
|
||||
assert.Equal(metrics[metricNames[2]].FloatValue, 0)
|
||||
assert.Equal(metrics[metricNames[2]][0].IntValue, 1)
|
||||
assert.Equal(metrics[metricNames[2]][0].FloatValue, 0)
|
||||
// waiting = 2
|
||||
assert.Equal(metrics[metricNames[3]].IntValue, 2)
|
||||
assert.Equal(metrics[metricNames[3]].FloatValue, 0)
|
||||
assert.Equal(metrics[metricNames[3]][0].IntValue, 2)
|
||||
assert.Equal(metrics[metricNames[3]][0].FloatValue, 0)
|
||||
}
|
||||
|
170
Godeps/_workspace/src/github.com/google/cadvisor/collector/prometheus_collector.go
generated
vendored
Normal file
170
Godeps/_workspace/src/github.com/google/cadvisor/collector/prometheus_collector.go
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
// Copyright 2015 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 (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/cadvisor/info/v1"
|
||||
)
|
||||
|
||||
type PrometheusCollector struct {
|
||||
//name of the collector
|
||||
name string
|
||||
|
||||
//rate at which metrics are collected
|
||||
pollingFrequency time.Duration
|
||||
|
||||
//holds information extracted from the config file for a collector
|
||||
configFile Prometheus
|
||||
}
|
||||
|
||||
//Returns a new collector using the information extracted from the configfile
|
||||
func NewPrometheusCollector(collectorName string, configFile []byte) (*PrometheusCollector, error) {
|
||||
var configInJSON Prometheus
|
||||
err := json.Unmarshal(configFile, &configInJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
minPollingFrequency := configInJSON.PollingFrequency
|
||||
|
||||
// Minimum supported frequency is 1s
|
||||
minSupportedFrequency := 1 * time.Second
|
||||
|
||||
if minPollingFrequency < minSupportedFrequency {
|
||||
minPollingFrequency = minSupportedFrequency
|
||||
}
|
||||
|
||||
//TODO : Add checks for validity of config file (eg : Accurate JSON fields)
|
||||
return &PrometheusCollector{
|
||||
name: collectorName,
|
||||
pollingFrequency: minPollingFrequency,
|
||||
configFile: configInJSON,
|
||||
}, nil
|
||||
}
|
||||
|
||||
//Returns name of the collector
|
||||
func (collector *PrometheusCollector) Name() string {
|
||||
return collector.name
|
||||
}
|
||||
|
||||
func getMetricData(line string) string {
|
||||
fields := strings.Fields(line)
|
||||
data := fields[3]
|
||||
if len(fields) > 4 {
|
||||
for i := range fields {
|
||||
if i > 3 {
|
||||
data = data + "_" + fields[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.TrimSpace(data)
|
||||
}
|
||||
|
||||
func (collector *PrometheusCollector) GetSpec() []v1.MetricSpec {
|
||||
specs := []v1.MetricSpec{}
|
||||
response, err := http.Get(collector.configFile.Endpoint)
|
||||
if err != nil {
|
||||
return specs
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
pageContent, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return specs
|
||||
}
|
||||
|
||||
lines := strings.Split(string(pageContent), "\n")
|
||||
for i, line := range lines {
|
||||
if strings.HasPrefix(line, "# HELP") {
|
||||
stopIndex := strings.Index(lines[i+2], "{")
|
||||
if stopIndex == -1 {
|
||||
stopIndex = strings.Index(lines[i+2], " ")
|
||||
}
|
||||
spec := v1.MetricSpec{
|
||||
Name: strings.TrimSpace(lines[i+2][0:stopIndex]),
|
||||
Type: v1.MetricType(getMetricData(lines[i+1])),
|
||||
Format: "float",
|
||||
Units: getMetricData(lines[i]),
|
||||
}
|
||||
specs = append(specs, spec)
|
||||
}
|
||||
}
|
||||
return specs
|
||||
}
|
||||
|
||||
//Returns collected metrics and the next collection time of the collector
|
||||
func (collector *PrometheusCollector) Collect(metrics map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) {
|
||||
currentTime := time.Now()
|
||||
nextCollectionTime := currentTime.Add(time.Duration(collector.pollingFrequency))
|
||||
|
||||
uri := collector.configFile.Endpoint
|
||||
response, err := http.Get(uri)
|
||||
if err != nil {
|
||||
return nextCollectionTime, nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
pageContent, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nextCollectionTime, nil, err
|
||||
}
|
||||
|
||||
var errorSlice []error
|
||||
lines := strings.Split(string(pageContent), "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
break
|
||||
}
|
||||
if !strings.HasPrefix(line, "# HELP") && !strings.HasPrefix(line, "# TYPE") {
|
||||
var metLabel string
|
||||
startLabelIndex := strings.Index(line, "{")
|
||||
spaceIndex := strings.Index(line, " ")
|
||||
if startLabelIndex == -1 {
|
||||
startLabelIndex = spaceIndex
|
||||
}
|
||||
|
||||
metName := strings.TrimSpace(line[0:startLabelIndex])
|
||||
|
||||
if startLabelIndex+1 <= spaceIndex-1 {
|
||||
metLabel = strings.TrimSpace(line[(startLabelIndex + 1):(spaceIndex - 1)])
|
||||
}
|
||||
|
||||
metVal, err := strconv.ParseFloat(line[spaceIndex+1:], 64)
|
||||
if err != nil {
|
||||
errorSlice = append(errorSlice, err)
|
||||
}
|
||||
if math.IsNaN(metVal) {
|
||||
metVal = 0
|
||||
}
|
||||
|
||||
metric := v1.MetricVal{
|
||||
Label: metLabel,
|
||||
FloatValue: metVal,
|
||||
Timestamp: currentTime,
|
||||
}
|
||||
metrics[metName] = append(metrics[metName], metric)
|
||||
}
|
||||
}
|
||||
return nextCollectionTime, metrics, compileErrors(errorSlice)
|
||||
}
|
64
Godeps/_workspace/src/github.com/google/cadvisor/collector/prometheus_collector_test.go
generated
vendored
Normal file
64
Godeps/_workspace/src/github.com/google/cadvisor/collector/prometheus_collector_test.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2015 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 (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/google/cadvisor/info/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPrometheus(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
//Create a prometheus collector using the config file 'sample_config_prometheus.json'
|
||||
configFile, err := ioutil.ReadFile("config/sample_config_prometheus.json")
|
||||
collector, err := NewPrometheusCollector("Prometheus", configFile)
|
||||
assert.NoError(err)
|
||||
assert.Equal(collector.name, "Prometheus")
|
||||
assert.Equal(collector.configFile.Endpoint, "http://localhost:8080/metrics")
|
||||
|
||||
tempServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
text := "# HELP go_gc_duration_seconds A summary of the GC invocation durations.\n"
|
||||
text += "# TYPE go_gc_duration_seconds summary\n"
|
||||
text += "go_gc_duration_seconds{quantile=\"0\"} 5.8348000000000004e-05\n"
|
||||
text += "go_gc_duration_seconds{quantile=\"1\"} 0.000499764\n"
|
||||
text += "# HELP go_goroutines Number of goroutines that currently exist.\n"
|
||||
text += "# TYPE go_goroutines gauge\n"
|
||||
text += "go_goroutines 16"
|
||||
fmt.Fprintln(w, text)
|
||||
}))
|
||||
|
||||
defer tempServer.Close()
|
||||
|
||||
collector.configFile.Endpoint = tempServer.URL
|
||||
metrics := map[string][]v1.MetricVal{}
|
||||
_, metrics, errMetric := collector.Collect(metrics)
|
||||
|
||||
assert.NoError(errMetric)
|
||||
|
||||
go_gc_duration := metrics["go_gc_duration_seconds"]
|
||||
assert.Equal(go_gc_duration[0].FloatValue, 5.8348000000000004e-05)
|
||||
assert.Equal(go_gc_duration[1].FloatValue, 0.000499764)
|
||||
|
||||
goRoutines := metrics["go_goroutines"]
|
||||
assert.Equal(goRoutines[0].FloatValue, 16)
|
||||
}
|
4
Godeps/_workspace/src/github.com/google/cadvisor/collector/types.go
generated
vendored
4
Godeps/_workspace/src/github.com/google/cadvisor/collector/types.go
generated
vendored
@ -27,7 +27,7 @@ type Collector interface {
|
||||
// Returns the next time this collector should be collected from.
|
||||
// Next collection time is always returned, even when an error occurs.
|
||||
// A collection time of zero means no more collection.
|
||||
Collect(map[string]v1.MetricVal) (time.Time, map[string]v1.MetricVal, error)
|
||||
Collect(map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error)
|
||||
|
||||
// Return spec for all metrics associated with this collector
|
||||
GetSpec() []v1.MetricSpec
|
||||
@ -45,7 +45,7 @@ type CollectorManager interface {
|
||||
// at which a collector will be ready to collect from.
|
||||
// Next collection time is always returned, even when an error occurs.
|
||||
// A collection time of zero means no more collection.
|
||||
Collect() (time.Time, map[string]v1.MetricVal, error)
|
||||
Collect() (time.Time, map[string][]v1.MetricVal, error)
|
||||
|
||||
// Get metric spec from all registered collectors.
|
||||
GetSpec() ([]v1.MetricSpec, error)
|
||||
|
11
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
11
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
@ -167,7 +167,16 @@ func libcontainerConfigToContainerSpec(config *libcontainerConfigs.Config, mi *i
|
||||
}
|
||||
spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.CpusetCpus, mi.NumCores)
|
||||
|
||||
spec.HasNetwork = len(config.Networks) > 0
|
||||
// Docker reports a loop device for containers with --net=host. Ignore
|
||||
// those too.
|
||||
networkCount := 0
|
||||
for _, n := range config.Networks {
|
||||
if n.Type != "loopback" {
|
||||
networkCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
spec.HasNetwork = networkCount > 0
|
||||
spec.HasDiskIo = true
|
||||
|
||||
return spec
|
||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go
generated
vendored
@ -427,7 +427,7 @@ type ContainerStats struct {
|
||||
TaskStats LoadStats `json:"task_stats,omitempty"`
|
||||
|
||||
//Custom metrics from all collectors
|
||||
CustomMetrics map[string]MetricVal `json:"custom_metrics,omitempty"`
|
||||
CustomMetrics map[string][]MetricVal `json:"custom_metrics,omitempty"`
|
||||
}
|
||||
|
||||
func timeEq(t1, t2 time.Time, tolerance time.Duration) bool {
|
||||
|
15
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/metric.go
generated
vendored
15
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/metric.go
generated
vendored
@ -56,7 +56,20 @@ type MetricSpec struct {
|
||||
}
|
||||
|
||||
// An exported metric.
|
||||
type MetricVal struct {
|
||||
type MetricValBasic struct {
|
||||
// Time at which the metric was queried
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
|
||||
// The value of the metric at this point.
|
||||
IntValue int64 `json:"int_value,omitempty"`
|
||||
FloatValue float64 `json:"float_value,omitempty"`
|
||||
}
|
||||
|
||||
// An exported metric.
|
||||
type MetricVal struct {
|
||||
// Label associated with a metric
|
||||
Label string `json:"label,omitempty"`
|
||||
|
||||
// Time at which the metric was queried
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
|
||||
|
4
Godeps/_workspace/src/github.com/google/cadvisor/info/v2/container.go
generated
vendored
4
Godeps/_workspace/src/github.com/google/cadvisor/info/v2/container.go
generated
vendored
@ -104,8 +104,8 @@ type ContainerStats struct {
|
||||
HasLoad bool `json:"has_load"`
|
||||
Load v1.LoadStats `json:"load_stats,omitempty"`
|
||||
// Custom Metrics
|
||||
HasCustomMetrics bool `json:"has_custom_metrics"`
|
||||
CustomMetrics map[string]v1.MetricVal `json:"custom_metrics,omitempty"`
|
||||
HasCustomMetrics bool `json:"has_custom_metrics"`
|
||||
CustomMetrics map[string][]v1.MetricVal `json:"custom_metrics,omitempty"`
|
||||
}
|
||||
|
||||
type Percentiles struct {
|
||||
|
6
Godeps/_workspace/src/github.com/google/cadvisor/manager/container.go
generated
vendored
6
Godeps/_workspace/src/github.com/google/cadvisor/manager/container.go
generated
vendored
@ -42,7 +42,7 @@ import (
|
||||
// Housekeeping interval.
|
||||
var HousekeepingInterval = flag.Duration("housekeeping_interval", 1*time.Second, "Interval between container housekeepings")
|
||||
|
||||
var cgroupPathRegExp = regexp.MustCompile(".*:devices:(.*?),.*")
|
||||
var cgroupPathRegExp = regexp.MustCompile(".*devices:(.*?)[,;$].*")
|
||||
|
||||
// Decay value used for load average smoothing. Interval length of 10 seconds is used.
|
||||
var loadDecay = math.Exp(float64(-1 * (*HousekeepingInterval).Seconds() / 10))
|
||||
@ -416,6 +416,8 @@ func (c *containerData) housekeeping() {
|
||||
// Schedule the next housekeeping. Sleep until that time.
|
||||
if time.Now().Before(next) {
|
||||
time.Sleep(next.Sub(time.Now()))
|
||||
} else {
|
||||
next = time.Now()
|
||||
}
|
||||
lastHousekeeping = next
|
||||
}
|
||||
@ -529,7 +531,7 @@ func (c *containerData) updateStats() error {
|
||||
return customStatsErr
|
||||
}
|
||||
|
||||
func (c *containerData) updateCustomStats() (map[string]info.MetricVal, error) {
|
||||
func (c *containerData) updateCustomStats() (map[string][]info.MetricVal, error) {
|
||||
_, customStats, customStatsErr := c.collectorManager.Collect()
|
||||
if customStatsErr != nil {
|
||||
if !c.handler.Exists() {
|
||||
|
49
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
49
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
@ -161,8 +161,7 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newManager.versionInfo = *versionInfo
|
||||
glog.Infof("Version: %+v", newManager.versionInfo)
|
||||
glog.Infof("Version: %+v", *versionInfo)
|
||||
|
||||
newManager.eventHandler = events.NewEventManager(parseEventsStoragePolicy())
|
||||
return newManager, nil
|
||||
@ -183,7 +182,6 @@ type manager struct {
|
||||
memoryCache *memory.InMemoryCache
|
||||
fsInfo fs.FsInfo
|
||||
machineInfo info.MachineInfo
|
||||
versionInfo info.VersionInfo
|
||||
quitChannels []chan error
|
||||
cadvisorContainer string
|
||||
inHostNamespace bool
|
||||
@ -221,7 +219,7 @@ func (self *manager) Start() error {
|
||||
} else {
|
||||
err = cpuLoadReader.Start()
|
||||
if err != nil {
|
||||
glog.Warning("Could not start cpu load stat collector: %s", err)
|
||||
glog.Warningf("Could not start cpu load stat collector: %s", err)
|
||||
} else {
|
||||
self.loadReader = cpuLoadReader
|
||||
}
|
||||
@ -658,7 +656,11 @@ func (m *manager) GetMachineInfo() (*info.MachineInfo, error) {
|
||||
}
|
||||
|
||||
func (m *manager) GetVersionInfo() (*info.VersionInfo, error) {
|
||||
return &m.versionInfo, nil
|
||||
// TODO: Consider caching this and periodically updating. The VersionInfo may change if
|
||||
// the docker daemon is started after the cAdvisor client is created. Caching the value
|
||||
// would be helpful so we would be able to return the last known docker version if
|
||||
// docker was down at the time of a query.
|
||||
return getVersionInfo()
|
||||
}
|
||||
|
||||
func (m *manager) Exists(containerName string) bool {
|
||||
@ -705,15 +707,28 @@ func (m *manager) registerCollectors(collectorConfigs map[string]string, cont *c
|
||||
}
|
||||
glog.V(3).Infof("Got config from %q: %q", v, configFile)
|
||||
|
||||
newCollector, err := collector.NewCollector(k, configFile)
|
||||
if err != nil {
|
||||
glog.Infof("failed to create collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
}
|
||||
err = cont.collectorManager.RegisterCollector(newCollector)
|
||||
if err != nil {
|
||||
glog.Infof("failed to register collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
if strings.HasPrefix(k, "prometheus") || strings.HasPrefix(k, "Prometheus") {
|
||||
newCollector, err := collector.NewPrometheusCollector(k, configFile)
|
||||
if err != nil {
|
||||
glog.Infof("failed to create collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
}
|
||||
err = cont.collectorManager.RegisterCollector(newCollector)
|
||||
if err != nil {
|
||||
glog.Infof("failed to register collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
newCollector, err := collector.NewCollector(k, configFile)
|
||||
if err != nil {
|
||||
glog.Infof("failed to create collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
}
|
||||
err = cont.collectorManager.RegisterCollector(newCollector)
|
||||
if err != nil {
|
||||
glog.Infof("failed to register collector for container %q, config %q: %v", cont.info.Name, k, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -1136,8 +1151,12 @@ func (m *manager) DockerInfo() (DockerStatus, error) {
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
versionInfo, err := m.GetVersionInfo()
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
out := DockerStatus{}
|
||||
out.Version = m.versionInfo.DockerVersion
|
||||
out.Version = versionInfo.DockerVersion
|
||||
if val, ok := info["KernelVersion"]; ok {
|
||||
out.KernelVersion = val
|
||||
}
|
||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/metrics/prometheus.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/metrics/prometheus.go
generated
vendored
@ -392,7 +392,7 @@ func (c *PrometheusCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
containers, err := c.infoProvider.SubcontainersInfo("/", &info.ContainerInfoRequest{NumStats: 1})
|
||||
if err != nil {
|
||||
c.errors.Set(1)
|
||||
glog.Warning("Couldn't get containers: %s", err)
|
||||
glog.Warningf("Couldn't get containers: %s", err)
|
||||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
|
29
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers.go
generated
vendored
29
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers.go
generated
vendored
@ -231,20 +231,21 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
||||
}
|
||||
|
||||
data := &pageData{
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Subcontainers: subcontainerLinks,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
IsRoot: cont.Name == "/",
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork || cont.Spec.HasFilesystem,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
Root: rootDir,
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Subcontainers: subcontainerLinks,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
IsRoot: cont.Name == "/",
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork || cont.Spec.HasFilesystem,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
|
||||
Root: rootDir,
|
||||
}
|
||||
err = pageTemplate.Execute(w, data)
|
||||
if err != nil {
|
||||
|
10
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers_html.go
generated
vendored
10
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers_html.go
generated
vendored
@ -221,6 +221,16 @@ const containersHtmlTemplate = `
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .CustomMetricsAvailable}}
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Application Metrics</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="custom-metrics-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
25
Godeps/_workspace/src/github.com/google/cadvisor/pages/docker.go
generated
vendored
25
Godeps/_workspace/src/github.com/google/cadvisor/pages/docker.go
generated
vendored
@ -129,18 +129,19 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error
|
||||
return err
|
||||
}
|
||||
data = &pageData{
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
Root: rootDir,
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
|
||||
Root: rootDir,
|
||||
}
|
||||
}
|
||||
|
||||
|
35
Godeps/_workspace/src/github.com/google/cadvisor/pages/pages.go
generated
vendored
35
Godeps/_workspace/src/github.com/google/cadvisor/pages/pages.go
generated
vendored
@ -44,23 +44,24 @@ type keyVal struct {
|
||||
}
|
||||
|
||||
type pageData struct {
|
||||
DisplayName string
|
||||
ContainerName string
|
||||
ParentContainers []link
|
||||
Subcontainers []link
|
||||
Spec info.ContainerSpec
|
||||
Stats []*info.ContainerStats
|
||||
MachineInfo *info.MachineInfo
|
||||
IsRoot bool
|
||||
ResourcesAvailable bool
|
||||
CpuAvailable bool
|
||||
MemoryAvailable bool
|
||||
NetworkAvailable bool
|
||||
FsAvailable bool
|
||||
Root string
|
||||
DockerStatus []keyVal
|
||||
DockerDriverStatus []keyVal
|
||||
DockerImages []manager.DockerImage
|
||||
DisplayName string
|
||||
ContainerName string
|
||||
ParentContainers []link
|
||||
Subcontainers []link
|
||||
Spec info.ContainerSpec
|
||||
Stats []*info.ContainerStats
|
||||
MachineInfo *info.MachineInfo
|
||||
IsRoot bool
|
||||
ResourcesAvailable bool
|
||||
CpuAvailable bool
|
||||
MemoryAvailable bool
|
||||
NetworkAvailable bool
|
||||
FsAvailable bool
|
||||
CustomMetricsAvailable bool
|
||||
Root string
|
||||
DockerStatus []keyVal
|
||||
DockerDriverStatus []keyVal
|
||||
DockerImages []manager.DockerImage
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
145
Godeps/_workspace/src/github.com/google/cadvisor/pages/static/containers_js.go
generated
vendored
145
Godeps/_workspace/src/github.com/google/cadvisor/pages/static/containers_js.go
generated
vendored
@ -645,6 +645,15 @@ function drawCharts(machineInfo, containerInfo) {
|
||||
});
|
||||
}
|
||||
|
||||
// Custom Metrics
|
||||
if (containerInfo.spec.has_custom_metrics) {
|
||||
steps.push(function() {
|
||||
getCustomMetrics(window.cadvisor.rootDir, window.cadvisor.containerName, function(metricsInfo) {
|
||||
drawCustomMetrics("custom-metrics-chart", containerInfo, metricsInfo)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
stepExecute(steps);
|
||||
}
|
||||
|
||||
@ -696,12 +705,144 @@ function refreshStats() {
|
||||
}
|
||||
if (containerInfo.spec.has_network) {
|
||||
startNetwork("network-selection", containerInfo);
|
||||
}
|
||||
if (containerInfo.spec.has_custom_metrics) {
|
||||
startCustomMetrics("custom-metrics-chart", containerInfo);
|
||||
}
|
||||
}
|
||||
drawCharts(machineInfo, containerInfo);
|
||||
});
|
||||
}
|
||||
|
||||
function addAllLabels(containerInfo, metricsInfo) {
|
||||
if (metricsInfo.length == 0) {
|
||||
return;
|
||||
}
|
||||
var metricSpec = containerInfo.spec.custom_metrics;
|
||||
for (var containerName in metricsInfo) {
|
||||
var container = metricsInfo[containerName];
|
||||
for (i=0; i<metricSpec.length; i++) {
|
||||
metricName = metricSpec[i].name;
|
||||
metricLabelVal = container[metricName];
|
||||
firstLabel = true;
|
||||
for (var label in metricLabelVal) {
|
||||
if (label == "") {
|
||||
$('#button-'+metricName).hide();
|
||||
}
|
||||
|
||||
$("#"+metricName+"_labels").append($("<li>")
|
||||
.attr("role", "presentation")
|
||||
.append($("<a>")
|
||||
.attr("role", "menuitem")
|
||||
.click(setLabel.bind(null, metricName, label))
|
||||
.text(label)));
|
||||
if (firstLabel) {
|
||||
firstLabel = false;
|
||||
setLabel(metricName, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMetricIndex(metricName) {
|
||||
for (i = 0; i<window.cadvisor.metricLabelPair.length; ++i) {
|
||||
if (window.cadvisor.metricLabelPair[i][0] == metricName)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function setLabel(metric, label) {
|
||||
$("#"+metric+"-selection-text")
|
||||
.empty()
|
||||
.append($("<span>").text("Label: "))
|
||||
.append($("<b>").text(label))
|
||||
|
||||
index = getMetricIndex(metric);
|
||||
if (index == -1) {
|
||||
window.cadvisor.metricLabelPair.push([metric, label]);
|
||||
} else {
|
||||
window.cadvisor.metricLabelPair[index][1] = label;
|
||||
}
|
||||
|
||||
refreshStats();
|
||||
}
|
||||
|
||||
function getSelectedLabel(metricName) {
|
||||
index = getMetricIndex(metricName);
|
||||
if (index == -1)
|
||||
return "";
|
||||
return window.cadvisor.metricLabelPair[index][1];
|
||||
}
|
||||
|
||||
function startCustomMetrics(elementId, containerInfo) {
|
||||
var metricSpec = containerInfo.spec.custom_metrics;
|
||||
var metricStats = containerInfo.stats.custom_metrics;
|
||||
var el=$("<div>");
|
||||
|
||||
if (metricSpec.length < window.cadvisor.maxCustomMetrics)
|
||||
window.cadvisor.maxCustomMetrics = metricSpec.length
|
||||
for (i = 0; i<window.cadvisor.maxCustomMetrics; i++) {
|
||||
metricName = metricSpec[i].name;
|
||||
var divText = "<div class='dropdown'> <button class='btn btn-default dropdown-toggle' type='button' id='button-"+metricName;
|
||||
divText += "' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>";
|
||||
divText += "<span id='"+metricName+"-selection-text'></span> <span class='caret'></span> </button>";
|
||||
divText += "<ul id='"+metricName+"_labels' class='dropdown-menu' role='menu' aria-labelledby='button-"+metricName+ "'> </ul> </div>";
|
||||
divText += "<div id='"+elementId+"-"+metricName+"'> </div>";
|
||||
el.append($(divText));
|
||||
}
|
||||
el.append($("</div>"));
|
||||
|
||||
$("#"+elementId).append(el);
|
||||
}
|
||||
|
||||
function getCustomMetrics(rootDir, containerName, callback) {
|
||||
$.getJSON(rootDir + "api/v2.0/appmetrics/" + containerName)
|
||||
.done(function(data) {
|
||||
callback(data);
|
||||
})
|
||||
.fail(function(jqhxr, textStatus, error) {
|
||||
callback([]);
|
||||
});
|
||||
}
|
||||
|
||||
function drawCustomMetrics(elementId, containerInfo, metricsInfo) {
|
||||
if(metricsInfo.length == 0) {
|
||||
return;
|
||||
}
|
||||
var metricSpec = containerInfo.spec.custom_metrics;
|
||||
for (var containerName in metricsInfo) {
|
||||
var container = metricsInfo[containerName];
|
||||
for (i=0; i<window.cadvisor.maxCustomMetrics; i++) {
|
||||
metricName = metricSpec[i].name;
|
||||
metricUnits = metricSpec[i].units;
|
||||
var titles = ["Time", metricName];
|
||||
metricLabelVal = container[metricName];
|
||||
if (window.cadvisor.firstCustomCollection) {
|
||||
window.cadvisor.firstCustomCollection = false;
|
||||
addAllLabels(containerInfo, metricsInfo);
|
||||
}
|
||||
var data = [];
|
||||
selectedLabel = getSelectedLabel(metricName);
|
||||
metricVal = metricLabelVal[selectedLabel];
|
||||
for (var index in metricVal) {
|
||||
metric = metricVal[index];
|
||||
var elements = [];
|
||||
for (var attribute in metric) {
|
||||
value = metric[attribute];
|
||||
elements.push(value);
|
||||
}
|
||||
if (elements.length<2) {
|
||||
elements.push(0);
|
||||
}
|
||||
data.push(elements);
|
||||
}
|
||||
drawLineChart(titles, data, elementId+"-"+metricName, metricUnits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Executed when the page finishes loading.
|
||||
function startPage(containerName, hasCpu, hasMemory, rootDir, isRoot) {
|
||||
// Don't fetch data if we don't have any resource.
|
||||
@ -715,6 +856,10 @@ function startPage(containerName, hasCpu, hasMemory, rootDir, isRoot) {
|
||||
window.cadvisor.rootDir = rootDir;
|
||||
window.cadvisor.containerName = containerName;
|
||||
|
||||
window.cadvisor.firstCustomCollection = true;
|
||||
window.cadvisor.metricLabelPair = [];
|
||||
window.cadvisor.maxCustomMetrics = 10;
|
||||
|
||||
// Draw process information at start and refresh every 60s.
|
||||
getProcessInfo(rootDir, containerName, function(processInfo) {
|
||||
drawProcesses(isRoot, rootDir, processInfo)
|
||||
|
116
Godeps/_workspace/src/github.com/google/cadvisor/storage/stdout/stdout.go
generated
vendored
Normal file
116
Godeps/_workspace/src/github.com/google/cadvisor/storage/stdout/stdout.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright 2015 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 stdout
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
)
|
||||
|
||||
type stdoutStorage struct {
|
||||
Namespace string
|
||||
}
|
||||
|
||||
const (
|
||||
colCpuCumulativeUsage = "cpu_cumulative_usage"
|
||||
// Memory Usage
|
||||
colMemoryUsage = "memory_usage"
|
||||
// Working set size
|
||||
colMemoryWorkingSet = "memory_working_set"
|
||||
// Cumulative count of bytes received.
|
||||
colRxBytes = "rx_bytes"
|
||||
// Cumulative count of receive errors encountered.
|
||||
colRxErrors = "rx_errors"
|
||||
// Cumulative count of bytes transmitted.
|
||||
colTxBytes = "tx_bytes"
|
||||
// Cumulative count of transmit errors encountered.
|
||||
colTxErrors = "tx_errors"
|
||||
// Filesystem summary
|
||||
colFsSummary = "fs_summary"
|
||||
// Filesystem limit.
|
||||
colFsLimit = "fs_limit"
|
||||
// Filesystem usage.
|
||||
colFsUsage = "fs_usage"
|
||||
)
|
||||
|
||||
func (driver *stdoutStorage) containerStatsToValues(stats *info.ContainerStats) (series map[string]uint64) {
|
||||
series = make(map[string]uint64)
|
||||
|
||||
// Cumulative Cpu Usage
|
||||
series[colCpuCumulativeUsage] = stats.Cpu.Usage.Total
|
||||
|
||||
// Memory Usage
|
||||
series[colMemoryUsage] = stats.Memory.Usage
|
||||
|
||||
// Working set size
|
||||
series[colMemoryWorkingSet] = stats.Memory.WorkingSet
|
||||
|
||||
// Network stats.
|
||||
series[colRxBytes] = stats.Network.RxBytes
|
||||
series[colRxErrors] = stats.Network.RxErrors
|
||||
series[colTxBytes] = stats.Network.TxBytes
|
||||
series[colTxErrors] = stats.Network.TxErrors
|
||||
|
||||
return series
|
||||
}
|
||||
|
||||
func (driver *stdoutStorage) containerFsStatsToValues(series *map[string]uint64, stats *info.ContainerStats) {
|
||||
for _, fsStat := range stats.Filesystem {
|
||||
// Summary stats.
|
||||
(*series)[colFsSummary+"."+colFsLimit] += fsStat.Limit
|
||||
(*series)[colFsSummary+"."+colFsUsage] += fsStat.Usage
|
||||
|
||||
// Per device stats.
|
||||
(*series)[fsStat.Device+"."+colFsLimit] = fsStat.Limit
|
||||
(*series)[fsStat.Device+"."+colFsUsage] = fsStat.Usage
|
||||
}
|
||||
}
|
||||
|
||||
func (driver *stdoutStorage) AddStats(ref info.ContainerReference, stats *info.ContainerStats) error {
|
||||
if stats == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
containerName := ref.Name
|
||||
if len(ref.Aliases) > 0 {
|
||||
containerName = ref.Aliases[0]
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString(fmt.Sprintf("cName=%s host=%s", containerName, driver.Namespace))
|
||||
|
||||
series := driver.containerStatsToValues(stats)
|
||||
driver.containerFsStatsToValues(&series, stats)
|
||||
for key, value := range series {
|
||||
buffer.WriteString(fmt.Sprintf(" %s=%v", key, value))
|
||||
}
|
||||
|
||||
_, err := fmt.Println(buffer.String())
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (driver *stdoutStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func New(namespace string) (*stdoutStorage, error) {
|
||||
stdoutStorage := &stdoutStorage{
|
||||
Namespace: namespace,
|
||||
}
|
||||
return stdoutStorage, nil
|
||||
}
|
2
Godeps/_workspace/src/github.com/google/cadvisor/utils/cloudinfo/gce.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/utils/cloudinfo/gce.go
generated
vendored
@ -17,8 +17,8 @@ package cloudinfo
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/gcloud-golang/compute/metadata"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"google.golang.org/cloud/compute/metadata"
|
||||
)
|
||||
|
||||
func onGCE() bool {
|
||||
|
Loading…
Reference in New Issue
Block a user