@@ -18,21 +18,65 @@ limitations under the License.
1818package updater
1919
2020import (
21+ "strconv"
22+
2123 "github.com/prometheus/client_golang/prometheus"
2224 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics"
2325)
2426
2527const (
2628 metricsNamespace = metrics .TopMetricsNamespace + "updater"
29+
30+ maxVpaSizeLog = 20
31+ // maxVpaSize = 2 ^ maxVpaSizeLog
32+ maxVpaSize = 1024 * 1024
2733)
2834
35+ // SizeBasedGauge is a wrapper for incrementally recording values indexed by log2(VPA size)
36+ type SizeBasedGauge struct {
37+ values map [int ]int
38+ gauge * prometheus.GaugeVec
39+ }
40+
2941var (
30- evictedCount = prometheus .NewCounter (
42+ controlledCount = prometheus .NewGaugeVec (
43+ prometheus.GaugeOpts {
44+ Namespace : metricsNamespace ,
45+ Name : "controlled_pods_total" ,
46+ Help : "Number of Pods controlled by VPA updater." ,
47+ }, []string {"vpa_size_log2" },
48+ )
49+
50+ evictableCount = prometheus .NewGaugeVec (
51+ prometheus.GaugeOpts {
52+ Namespace : metricsNamespace ,
53+ Name : "evictable_pods_total" ,
54+ Help : "Number of Pods matching evicition criteria." ,
55+ }, []string {"vpa_size_log2" },
56+ )
57+
58+ evictedCount = prometheus .NewCounterVec (
3159 prometheus.CounterOpts {
3260 Namespace : metricsNamespace ,
3361 Name : "evicted_pods_total" ,
3462 Help : "Number of Pods evicted by Updater to apply a new recommendation." ,
35- },
63+ }, []string {"vpa_size_log2" },
64+ )
65+
66+ vpasWithEvictablePodsCount = prometheus .NewGaugeVec (
67+ prometheus.GaugeOpts {
68+ Namespace : metricsNamespace ,
69+ Name : "vpas_with_evictable_pods_total" ,
70+ Help : "Number of VPA objects with at least one Pod matching evicition criteria." ,
71+ }, []string {"vpa_size_log2" },
72+ )
73+
74+ vpasWithEvictedPodsCount = prometheus .NewGaugeVec (
75+ prometheus.GaugeOpts {
76+ Namespace : metricsNamespace ,
77+ Name : "vpas_with_evicted_pods_total" ,
78+ Help : "Number of VPA objects with at least one evicted Pod." ,
79+ }, []string {"vpa_size_log2" },
3680 )
3781
3882 functionLatency = metrics .CreateExecutionTimeMetric (metricsNamespace ,
@@ -41,16 +85,77 @@ var (
4185
4286// Register initializes all metrics for VPA Updater
4387func Register () {
44- prometheus .MustRegister (evictedCount )
45- prometheus .MustRegister (functionLatency )
88+ prometheus .MustRegister (controlledCount , evictableCount , evictedCount , vpasWithEvictablePodsCount , vpasWithEvictedPodsCount , functionLatency )
4689}
4790
4891// NewExecutionTimer provides a timer for Updater's RunOnce execution
4992func NewExecutionTimer () * metrics.ExecutionTimer {
5093 return metrics .NewExecutionTimer (functionLatency )
5194}
5295
53- // AddEvictedPod increases the counter of pods evicted by VPA
54- func AddEvictedPod () {
55- evictedCount .Add (1 )
96+ // newSizeBasedGauge provides a wrapper for counting items in a loop
97+ func newSizeBasedGauge (gauge * prometheus.GaugeVec ) * SizeBasedGauge {
98+ obj := SizeBasedGauge {
99+ values : make (map [int ]int ),
100+ gauge : gauge ,
101+ }
102+
103+ // initialize with empty data so we can clean stale gauge values in Observe
104+ for i := 0 ; i <= maxVpaSizeLog ; i ++ {
105+ obj .values [i ] = 0
106+ }
107+
108+ return & obj
109+ }
110+
111+ // NewControlledPodsCounter returns a wrapper for counting Pods controlled by Updater
112+ func NewControlledPodsCounter () * SizeBasedGauge {
113+ return newSizeBasedGauge (controlledCount )
114+ }
115+
116+ // NewEvictablePodsCounter returns a wrapper for counting Pods which are matching eviction criteria
117+ func NewEvictablePodsCounter () * SizeBasedGauge {
118+ return newSizeBasedGauge (evictableCount )
119+ }
120+
121+ // NewVpasWithEvictablePodsCounter returns a wrapper for counting VPA objects with Pods matching eviction criteria
122+ func NewVpasWithEvictablePodsCounter () * SizeBasedGauge {
123+ return newSizeBasedGauge (vpasWithEvictablePodsCount )
124+ }
125+
126+ // NewVpasWithEvictedPodsCounter returns a wrapper for counting VPA objects with evicted Pods
127+ func NewVpasWithEvictedPodsCounter () * SizeBasedGauge {
128+ return newSizeBasedGauge (vpasWithEvictedPodsCount )
129+ }
130+
131+ func getVpaSizeLog2 (vpaSize int ) int {
132+ if vpaSize >= maxVpaSize {
133+ return maxVpaSizeLog
134+ }
135+
136+ log2 := 0
137+ for vpaSize > 1 {
138+ log2 ++
139+ vpaSize >>= 1
140+ }
141+ return log2
142+ }
143+
144+ // AddEvictedPod increases the counter of pods evicted by Updater, by given VPA size
145+ func AddEvictedPod (vpaSize int ) {
146+ log2 := getVpaSizeLog2 (vpaSize )
147+ evictedCount .WithLabelValues (strconv .Itoa (log2 )).Inc ()
148+ }
149+
150+ // Add increases the counter for the given VPA size
151+ func (g * SizeBasedGauge ) Add (vpaSize int , value int ) {
152+ log2 := getVpaSizeLog2 (vpaSize )
153+ g .values [log2 ] += value
154+ }
155+
156+ // Observe stores the recorded values into metrics object associated with the wrapper
157+ func (g * SizeBasedGauge ) Observe () {
158+ for log2 , value := range g .values {
159+ g .gauge .WithLabelValues (strconv .Itoa (log2 )).Set (float64 (value ))
160+ }
56161}
0 commit comments