Skip to content

Commit 9e06c30

Browse files
committed
Finalized new client golang abstraction and using it.
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
1 parent b12c3bd commit 9e06c30

File tree

4 files changed

+138
-114
lines changed

4 files changed

+138
-114
lines changed

info/v2/container.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ type RequestOptions struct {
270270
// Whether to include stats for child subcontainers.
271271
Recursive bool `json:"recursive"`
272272
// Update stats if they are older than MaxAge
273-
// nil indicates no update, and 0 will always trigger an update.
273+
// nil and 0 indicates always update.
274274
MaxAge *time.Duration `json:"max_age"`
275275
}
276276

metrics/prometheus.go

Lines changed: 110 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,26 @@ import (
2323
"github.com/google/cadvisor/container"
2424
info "github.com/google/cadvisor/info/v1"
2525
v2 "github.com/google/cadvisor/info/v2"
26+
dto "github.com/prometheus/client_model/go"
2627

2728
"github.com/prometheus/client_golang/prometheus"
2829
"k8s.io/klog/v2"
2930
"k8s.io/utils/clock"
3031
)
3132

33+
const (
34+
// ContainerLabelPrefix is the prefix added to all container labels.
35+
ContainerLabelPrefix = "container_label_"
36+
// ContainerEnvPrefix is the prefix added to all env variable labels.
37+
ContainerEnvPrefix = "container_env_"
38+
// LabelID is the name of the id label.
39+
LabelID = "id"
40+
// LabelName is the name of the name label.
41+
LabelName = "name"
42+
// LabelImage is the name of the image label.
43+
LabelImage = "image"
44+
)
45+
3246
// asFloat64 converts a uint64 into a float64.
3347
func asFloat64(v uint64) float64 { return float64(v) }
3448

@@ -83,45 +97,33 @@ type containerMetric struct {
8397
getValues func(s *info.ContainerStats) metricValues
8498
}
8599

86-
func (cm *containerMetric) desc(session *prometheus.CollectSession, baseLabels []string) *prometheus.Desc {
87-
if session == nil {
88-
return prometheus.NewDesc(cm.name, cm.help, append(baseLabels, cm.extraLabels...), nil)
89-
}
90-
return session.NewDesc(cm.name, cm.help, append(baseLabels, cm.extraLabels...), nil)
91-
}
92-
93100
// ContainerLabelsFunc defines all base labels and their values attached to
94101
// each metric exported by cAdvisor.
95102
type ContainerLabelsFunc func(*info.ContainerInfo) map[string]string
96103

97104
// PrometheusCollector implements prometheus.Collector.
98105
type PrometheusCollector struct {
99106
infoProvider infoProvider
100-
errors prometheus.Gauge
101107
containerMetrics []containerMetric
102108
containerLabelsFunc ContainerLabelsFunc
103109
includedMetrics container.MetricSet
104110
opts v2.RequestOptions
105111

106-
cache prometheus.CachedCollector
112+
lastUpdate time.Time
113+
cache *prometheus.CachedCollector
107114
}
108115

109116
// NewPrometheusCollector returns a new PrometheusCollector. The passed
110117
// ContainerLabelsFunc specifies which base labels will be attached to all
111118
// exported metrics. If left to nil, the DefaultContainerLabels function
112119
// will be used instead.
113-
func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc, includedMetrics container.MetricSet, now clock.Clock, opts v2.RequestOptions) *PrometheusCollector {
120+
func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc, includedMetrics container.MetricSet, now clock.Clock) *PrometheusCollector {
114121
if f == nil {
115122
f = DefaultContainerLabels
116123
}
117124
c := &PrometheusCollector{
118125
infoProvider: i,
119126
containerLabelsFunc: f,
120-
errors: prometheus.NewGauge(prometheus.GaugeOpts{
121-
Namespace: "container",
122-
Name: "scrape_error",
123-
Help: "1 if there was an error while getting container metrics, 0 otherwise",
124-
}),
125127
containerMetrics: []containerMetric{
126128
{
127129
name: "container_last_seen",
@@ -136,7 +138,7 @@ func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc, includedMetri
136138
},
137139
},
138140
includedMetrics: includedMetrics,
139-
opts: opts,
141+
cache: prometheus.NewCachedCollector(),
140142
}
141143
if includedMetrics.Has(container.CpuUsageMetrics) {
142144
c.containerMetrics = append(c.containerMetrics, []containerMetric{
@@ -1776,51 +1778,53 @@ func NewPrometheusCollector(i infoProvider, f ContainerLabelsFunc, includedMetri
17761778
return c
17771779
}
17781780

1779-
var (
1780-
versionInfoDesc = prometheus.NewDesc("cadvisor_version_info", "A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.", []string{"kernelVersion", "osVersion", "dockerVersion", "cadvisorVersion", "cadvisorRevision"}, nil)
1781-
startTimeDesc = prometheus.NewDesc("container_start_time_seconds", "Start time of the container since unix epoch in seconds.", nil, nil)
1782-
cpuPeriodDesc = prometheus.NewDesc("container_spec_cpu_period", "CPU period of the container.", nil, nil)
1783-
cpuQuotaDesc = prometheus.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", nil, nil)
1784-
cpuSharesDesc = prometheus.NewDesc("container_spec_cpu_shares", "CPU share of the container.", nil, nil)
1785-
)
1781+
func (c *PrometheusCollector) SetOpts(opts v2.RequestOptions) {
1782+
c.opts = opts
1783+
}
1784+
1785+
1786+
//// Describe describes all the metrics ever exported by cadvisor. It
1787+
//// implements prometheus.PrometheusCollector.
1788+
//func (c *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) {
1789+
// panic("unpexected")
1790+
// //c.errors.Describe(ch)
1791+
// for _, cm := range c.containerMetrics {
1792+
// ch <- cm.desc(nil, []string{})
1793+
// }
1794+
//}
1795+
1796+
// Collect fetches latest statistics about containers and exposes them to Prometheus handler that converts them
1797+
// to expected Prometheus format.
1798+
// Based on option it
1799+
// * ask the latest from provided services.
1800+
// * returns cached results if until time expires.
1801+
//
1802+
// It implements prometheus.rawCollector.
1803+
func (c *PrometheusCollector) Collect() []*dto.MetricFamily {
1804+
if c.opts.MaxAge == nil || time.Since(c.lastUpdate) > *c.opts.MaxAge {
1805+
c.lastUpdate = time.Now()
1806+
session := c.cache.NewSession()
1807+
1808+
errorsGauge := 0
1809+
if err := c.collectVersionInfo(session); err != nil {
1810+
errorsGauge = 1
1811+
klog.Warningf("Couldn't get version info: %s", err)
1812+
}
1813+
if err := c.collectContainersInfo(session); err != nil {
1814+
errorsGauge = 1
1815+
klog.Warningf("Couldn't get containers: %s", err)
1816+
}
17861817

1787-
// Describe describes all the metrics ever exported by cadvisor. It
1788-
// implements prometheus.PrometheusCollector.
1789-
func (c *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) {
1790-
c.errors.Describe(ch)
1791-
for _, cm := range c.containerMetrics {
1792-
ch <- cm.desc(nil, []string{})
1818+
session.MustAddMetric(
1819+
"container_scrape_error","1 if there was an error while getting container metrics, 0 otherwise",
1820+
nil, nil,prometheus.GaugeValue, float64(errorsGauge),nil,
1821+
)
1822+
session.Commit()
17931823
}
1794-
ch <- startTimeDesc
1795-
ch <- cpuPeriodDesc
1796-
ch <- cpuQuotaDesc
1797-
ch <- cpuSharesDesc
1798-
ch <- versionInfoDesc
1799-
}
18001824

1801-
// Collect fetches the stats from all containers and delivers them as
1802-
// Prometheus metrics. It implements prometheus.PrometheusCollector.
1803-
func (c *PrometheusCollector) Collect(ch chan<- prometheus.Metric) {
1804-
session := c.cache.NewSession()
1805-
c.errors.Set(0)
1806-
c.collectVersionInfo(session, ch)
1807-
c.collectContainersInfo(session, ch)
1808-
c.errors.Collect(ch)
1825+
return c.cache.Collect()
18091826
}
18101827

1811-
const (
1812-
// ContainerLabelPrefix is the prefix added to all container labels.
1813-
ContainerLabelPrefix = "container_label_"
1814-
// ContainerEnvPrefix is the prefix added to all env variable labels.
1815-
ContainerEnvPrefix = "container_env_"
1816-
// LabelID is the name of the id label.
1817-
LabelID = "id"
1818-
// LabelName is the name of the name label.
1819-
LabelName = "name"
1820-
// LabelImage is the name of the image label.
1821-
LabelImage = "image"
1822-
)
1823-
18241828
// DefaultContainerLabels implements ContainerLabelsFunc. It exports the
18251829
// container name, first alias, image name as well as all its env and label
18261830
// values.
@@ -1869,12 +1873,10 @@ func BaseContainerLabels(whiteList []string) func(container *info.ContainerInfo)
18691873
}
18701874
}
18711875

1872-
func (c *PrometheusCollector) collectContainersInfo(session *prometheus.CollectSession, ch chan<- prometheus.Metric) {
1876+
func (c *PrometheusCollector) collectContainersInfo(session *prometheus.CollectSession) error {
18731877
containers, err := c.infoProvider.GetRequestedContainersInfo("/", c.opts)
18741878
if err != nil {
1875-
c.errors.Set(1)
1876-
klog.Warningf("Couldn't get containers: %s", err)
1877-
return
1879+
return err
18781880
}
18791881
rawLabels := map[string]struct{}{}
18801882
for _, container := range containers {
@@ -1903,30 +1905,43 @@ func (c *PrometheusCollector) collectContainersInfo(session *prometheus.CollectS
19031905
}
19041906

19051907
// Container spec.
1906-
desc := session.NewDesc("container_start_time_seconds", "Start time of the container since unix epoch in seconds.", labels, nil)
1907-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(cont.Spec.CreationTime.Unix()), values...)
1908+
session.MustAddMetric(
1909+
"container_start_time_seconds","Start time of the container since unix epoch in seconds.",
1910+
labels, values,prometheus.GaugeValue, float64(cont.Spec.CreationTime.Unix()),nil,
1911+
)
19081912

19091913
if cont.Spec.HasCpu {
1910-
desc = session.NewDesc("container_spec_cpu_period", "CPU period of the container.", labels, nil)
1911-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(cont.Spec.Cpu.Period), values...)
1914+
session.MustAddMetric(
1915+
"container_spec_cpu_period", "CPU period of the container.",
1916+
labels, values,prometheus.GaugeValue, float64(cont.Spec.Cpu.Period),nil,
1917+
)
19121918
if cont.Spec.Cpu.Quota != 0 {
1913-
desc = session.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", labels, nil)
1914-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(cont.Spec.Cpu.Quota), values...)
1919+
session.MustAddMetric(
1920+
"container_spec_cpu_quota", "CPU quota of the container.",
1921+
labels, values,prometheus.GaugeValue, float64(cont.Spec.Cpu.Quota),nil,
1922+
)
19151923
}
1916-
desc := session.NewDesc("container_spec_cpu_shares", "CPU share of the container.", labels, nil)
1917-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(cont.Spec.Cpu.Limit), values...)
1918-
1924+
session.MustAddMetric(
1925+
"container_spec_cpu_shares", "CPU share of the container.",
1926+
labels, values, prometheus.GaugeValue, float64(cont.Spec.Cpu.Limit),nil,
1927+
)
19191928
}
19201929
if cont.Spec.HasMemory {
1921-
desc := session.NewDesc("container_spec_memory_limit_bytes", "Memory limit for the container.", labels, nil)
1922-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.Limit), values...)
1923-
desc = session.NewDesc("container_spec_memory_swap_limit_bytes", "Memory swap limit for the container.", labels, nil)
1924-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.SwapLimit), values...)
1925-
desc = session.NewDesc("container_spec_memory_reservation_limit_bytes", "Memory reservation limit for the container.", labels, nil)
1926-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.Reservation), values...)
1930+
session.MustAddMetric(
1931+
"container_spec_memory_limit_bytes", "Memory limit for the container.",
1932+
labels,values, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.Limit),nil,
1933+
)
1934+
session.MustAddMetric(
1935+
"container_spec_memory_swap_limit_bytes", "Memory swap limit for the container.",
1936+
labels,values, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.SwapLimit), nil,
1937+
)
1938+
session.MustAddMetric(
1939+
"container_spec_memory_reservation_limit_bytes", "Memory reservation limit for the container.",
1940+
labels, values, prometheus.GaugeValue, specMemoryValue(cont.Spec.Memory.Reservation), nil,
1941+
)
19271942
}
19281943

1929-
// Now for the actual metrics
1944+
// Now for the actual metrics.
19301945
if len(cont.Stats) == 0 {
19311946
continue
19321947
}
@@ -1935,11 +1950,11 @@ func (c *PrometheusCollector) collectContainersInfo(session *prometheus.CollectS
19351950
if cm.condition != nil && !cm.condition(cont.Spec) {
19361951
continue
19371952
}
1938-
desc := cm.desc(session, labels)
19391953
for _, metricValue := range cm.getValues(stats) {
1940-
ch <- prometheus.NewMetricWithTimestamp(
1941-
metricValue.timestamp,
1942-
prometheus.MustNewConstMetric(desc, cm.valueType, metricValue.value, append(values, metricValue.labels...)...),
1954+
session.MustAddMetric(
1955+
cm.name, cm.help,
1956+
append(labels, cm.extraLabels...), append(values, metricValue.labels...),
1957+
cm.valueType, metricValue.value, &metricValue.timestamp,
19431958
)
19441959
}
19451960
}
@@ -1954,22 +1969,30 @@ func (c *PrometheusCollector) collectContainersInfo(session *prometheus.CollectS
19541969
clabels = append(clabels, sanitizeLabelName("app_"+label))
19551970
cvalues = append(cvalues, value)
19561971
}
1957-
desc := session.NewDesc(metricLabel, "Custom application metric.", clabels, nil)
1958-
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, metric.FloatValue, cvalues...)
1972+
session.MustAddMetric(
1973+
metricLabel, "Custom application metric.",
1974+
clabels,cvalues, prometheus.GaugeValue, metric.FloatValue, nil,
1975+
)
19591976
}
19601977
}
19611978
}
19621979
}
1980+
return nil
19631981
}
19641982

1965-
func (c *PrometheusCollector) collectVersionInfo(session *prometheus.CollectSession, ch chan<- prometheus.Metric) {
1983+
func (c *PrometheusCollector) collectVersionInfo(session *prometheus.CollectSession) error {
19661984
versionInfo, err := c.infoProvider.GetVersionInfo()
19671985
if err != nil {
1968-
c.errors.Set(1)
1969-
klog.Warningf("Couldn't get version info: %s", err)
1970-
return
1986+
return err
19711987
}
1972-
ch <- prometheus.MustNewConstMetric(versionInfoDesc, prometheus.GaugeValue, 1, versionInfo.KernelVersion, versionInfo.ContainerOsVersion, versionInfo.DockerVersion, versionInfo.CadvisorVersion, versionInfo.CadvisorRevision)
1988+
session.MustAddMetric(
1989+
"cadvisor_version_info",
1990+
"A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.",
1991+
[]string{"kernelVersion", "osVersion", "dockerVersion", "cadvisorVersion", "cadvisorRevision"},
1992+
[]string{versionInfo.KernelVersion, versionInfo.ContainerOsVersion, versionInfo.DockerVersion, versionInfo.CadvisorVersion, versionInfo.CadvisorRevision},
1993+
prometheus.GaugeValue, 1, nil,
1994+
)
1995+
return nil
19731996
}
19741997

19751998
// Size after which we consider memory to be "unlimited". This is not

metrics/prometheus_bench_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,21 @@ func BenchmarkPrometheusCollector_Collect(b *testing.B) {
3737
infoProvider.containers[name] = genContainerInfo(name)
3838
}
3939

40-
reg := prometheus.NewRegistry()
41-
reg.MustRegister(NewPrometheusCollector(infoProvider, func(container *info.ContainerInfo) map[string]string {
40+
reg := prometheus.NewBlockingRegistry()
41+
c := NewPrometheusCollector(infoProvider, func(container *info.ContainerInfo) map[string]string {
4242
s := DefaultContainerLabels(container)
4343
s["zone.name"] = "hello"
4444
return s
45-
}, container.AllMetrics, now, v2.RequestOptions{}))
45+
}, container.AllMetrics, now)
46+
reg.MustRegisterRaw(c)
4647

48+
c.SetOpts(v2.RequestOptions{})
4749
var err error
50+
var done func()
4851
b.ResetTimer()
4952
for i := 0; i < b.N; i++ {
50-
mfsTmp, err = reg.Gather()
53+
mfsTmp, done, err = reg.Gather()
5154
require.NoError(b, err)
55+
done()
5256
}
5357
}

0 commit comments

Comments
 (0)