@@ -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.
3347func 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.
95102type ContainerLabelsFunc func (* info.ContainerInfo ) map [string ]string
96103
97104// PrometheusCollector implements prometheus.Collector.
98105type 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
0 commit comments