Skip to content

Commit 767af98

Browse files
authored
Merge pull request #1725 from tanguyfalconnet/feat/hpa/status_current_target
feat(hpa): status current metric
2 parents fad76e4 + 8e5d283 commit 767af98

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

docs/horizontalpodautoscaler-metrics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
| kube_horizontalpodautoscaler_spec_max_replicas | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; | STABLE |
1010
| kube_horizontalpodautoscaler_spec_min_replicas | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; | STABLE |
1111
| kube_horizontalpodautoscaler_spec_target_metric | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; <br> `metric_name`=&lt;metric-name&gt; <br> `metric_target_type`=&lt;value\|utilization\|average&gt; | EXPERIMENTAL |
12+
| kube_horizontalpodautoscaler_status_target_metric | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; <br> `metric_name`=&lt;metric-name&gt; <br> `metric_target_type`=&lt;value\|utilization\|average&gt; | EXPERIMENTAL |
1213
| kube_horizontalpodautoscaler_status_condition | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; <br> `condition`=&lt;hpa-condition&gt; <br> `status`=&lt;true\|false\|unknown&gt; | STABLE |
1314
| kube_horizontalpodautoscaler_status_current_replicas | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; | STABLE |
1415
| kube_horizontalpodautoscaler_status_desired_replicas | Gauge | `horizontalpodautoscaler`=&lt;hpa-name&gt; <br> `namespace`=&lt;hpa-namespace&gt; | STABLE |

internal/store/horizontalpodautoscaler.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,68 @@ func hpaMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat
184184
return &metric.Family{Metrics: ms}
185185
}),
186186
),
187+
*generator.NewFamilyGenerator(
188+
"kube_horizontalpodautoscaler_status_target_metric",
189+
"The current metric status used by this autoscaler when calculating the desired replica count.",
190+
metric.Gauge,
191+
"",
192+
wrapHPAFunc(func(a *autoscaling.HorizontalPodAutoscaler) *metric.Family {
193+
ms := make([]*metric.Metric, 0, len(a.Status.CurrentMetrics))
194+
for _, m := range a.Status.CurrentMetrics {
195+
var metricName string
196+
197+
// The variable maps the type of metric to the corresponding value
198+
metricMap := make(map[metricTargetType]float64)
199+
200+
switch m.Type {
201+
case autoscaling.ObjectMetricSourceType:
202+
metricName = m.Object.Metric.Name
203+
204+
if m.Object.Current.Value != nil {
205+
metricMap[value] = float64(m.Object.Current.Value.MilliValue()) / 1000
206+
}
207+
if m.Object.Current.AverageValue != nil {
208+
metricMap[average] = float64(m.Object.Current.AverageValue.MilliValue()) / 1000
209+
}
210+
case autoscaling.PodsMetricSourceType:
211+
metricName = m.Pods.Metric.Name
212+
213+
metricMap[average] = float64(m.Pods.Current.AverageValue.MilliValue()) / 1000
214+
case autoscaling.ResourceMetricSourceType:
215+
metricName = string(m.Resource.Name)
216+
217+
if m.Resource.Current.AverageUtilization != nil {
218+
metricMap[utilization] = float64(*m.Resource.Current.AverageUtilization)
219+
}
220+
221+
if m.Resource.Current.AverageValue != nil {
222+
metricMap[average] = float64(m.Resource.Current.AverageValue.MilliValue()) / 1000
223+
}
224+
case autoscaling.ExternalMetricSourceType:
225+
metricName = m.External.Metric.Name
226+
227+
if m.External.Current.Value != nil {
228+
metricMap[value] = float64(m.External.Current.Value.MilliValue()) / 1000
229+
}
230+
if m.External.Current.AverageValue != nil {
231+
metricMap[average] = float64(m.External.Current.AverageValue.MilliValue()) / 1000
232+
}
233+
default:
234+
// Skip unsupported metric type
235+
continue
236+
}
237+
238+
for metricTypeIndex, metricValue := range metricMap {
239+
ms = append(ms, &metric.Metric{
240+
LabelKeys: targetMetricLabels,
241+
LabelValues: []string{metricName, metricTypeIndex.String()},
242+
Value: metricValue,
243+
})
244+
}
245+
}
246+
return &metric.Family{Metrics: ms}
247+
}),
248+
),
187249
*generator.NewFamilyGenerator(
188250
"kube_horizontalpodautoscaler_status_current_replicas",
189251
"Current number of replicas of pods managed by this autoscaler.",

internal/store/horizontalpodautoscaler_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func TestHPAStore(t *testing.T) {
4242
# HELP kube_horizontalpodautoscaler_spec_max_replicas Upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas.
4343
# HELP kube_horizontalpodautoscaler_spec_min_replicas Lower limit for the number of pods that can be set by the autoscaler, default 1.
4444
# HELP kube_horizontalpodautoscaler_spec_target_metric The metric specifications used by this autoscaler when calculating the desired replica count.
45+
# HELP kube_horizontalpodautoscaler_status_target_metric The current metric status used by this autoscaler when calculating the desired replica count.
4546
# HELP kube_horizontalpodautoscaler_status_condition The condition of this autoscaler.
4647
# HELP kube_horizontalpodautoscaler_status_current_replicas Current number of replicas of pods managed by this autoscaler.
4748
# HELP kube_horizontalpodautoscaler_status_desired_replicas Desired number of replicas of pods managed by this autoscaler.
@@ -52,6 +53,7 @@ func TestHPAStore(t *testing.T) {
5253
# TYPE kube_horizontalpodautoscaler_spec_max_replicas gauge
5354
# TYPE kube_horizontalpodautoscaler_spec_min_replicas gauge
5455
# TYPE kube_horizontalpodautoscaler_spec_target_metric gauge
56+
# TYPE kube_horizontalpodautoscaler_status_target_metric gauge
5557
# TYPE kube_horizontalpodautoscaler_status_condition gauge
5658
# TYPE kube_horizontalpodautoscaler_status_current_replicas gauge
5759
# TYPE kube_horizontalpodautoscaler_status_desired_replicas gauge
@@ -179,7 +181,7 @@ func TestHPAStore(t *testing.T) {
179181
Name: "cpu",
180182
Current: autoscaling.MetricValueStatus{
181183
AverageValue: resourcePtr(resource.MustParse("7m")),
182-
AverageUtilization: new(int32),
184+
AverageUtilization: int32ptr(80),
183185
},
184186
},
185187
},
@@ -189,7 +191,7 @@ func TestHPAStore(t *testing.T) {
189191
Name: "memory",
190192
Current: autoscaling.MetricValueStatus{
191193
AverageValue: resourcePtr(resource.MustParse("26335914666m")),
192-
AverageUtilization: new(int32),
194+
AverageUtilization: int32ptr(80),
193195
},
194196
},
195197
},
@@ -213,6 +215,10 @@ func TestHPAStore(t *testing.T) {
213215
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 80
214216
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="sqs_jobs",metric_target_type="value",namespace="ns1"} 30
215217
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa1",metric_name="transactions_processed",metric_target_type="average",namespace="ns1"} 33
218+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa1",metric_name="cpu",metric_target_type="average",namespace="ns1"} 0.007
219+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa1",metric_name="cpu",metric_target_type="utilization",namespace="ns1"} 80
220+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa1",metric_name="memory",metric_target_type="average",namespace="ns1"} 2.6335914666e+07
221+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa1",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 80
216222
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa1",namespace="ns1",status="false"} 0
217223
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa1",namespace="ns1",status="true"} 1
218224
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa1",namespace="ns1",status="unknown"} 0
@@ -225,6 +231,7 @@ func TestHPAStore(t *testing.T) {
225231
"kube_horizontalpodautoscaler_spec_max_replicas",
226232
"kube_horizontalpodautoscaler_spec_min_replicas",
227233
"kube_horizontalpodautoscaler_spec_target_metric",
234+
"kube_horizontalpodautoscaler_status_target_metric",
228235
"kube_horizontalpodautoscaler_status_current_replicas",
229236
"kube_horizontalpodautoscaler_status_desired_replicas",
230237
"kube_horizontalpodautoscaler_status_condition",
@@ -368,6 +375,13 @@ func TestHPAStore(t *testing.T) {
368375
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa2",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 75
369376
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_errors_per_second",metric_target_type="value",namespace="ns1"} 100
370377
kube_horizontalpodautoscaler_spec_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_requests_per_second",metric_target_type="value",namespace="ns1"} 100
378+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="memory",metric_target_type="average",namespace="ns1"} 8.47775744e+08
379+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="memory",metric_target_type="utilization",namespace="ns1"} 28
380+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="average",namespace="ns1"} 0.062
381+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="cpu",metric_target_type="utilization",namespace="ns1"} 6
382+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_requests_per_second",metric_target_type="value",namespace="ns1"} 0
383+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_requests_per_second",metric_target_type="average",namespace="ns1"} 2.9
384+
kube_horizontalpodautoscaler_status_target_metric{horizontalpodautoscaler="hpa2",metric_name="traefik_backend_errors_per_second",metric_target_type="value",namespace="ns1"} 0
371385
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa2",namespace="ns1",status="false"} 0
372386
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa2",namespace="ns1",status="true"} 1
373387
kube_horizontalpodautoscaler_status_condition{condition="AbleToScale",horizontalpodautoscaler="hpa2",namespace="ns1",status="unknown"} 0
@@ -380,6 +394,7 @@ func TestHPAStore(t *testing.T) {
380394
"kube_horizontalpodautoscaler_spec_max_replicas",
381395
"kube_horizontalpodautoscaler_spec_min_replicas",
382396
"kube_horizontalpodautoscaler_spec_target_metric",
397+
"kube_horizontalpodautoscaler_status_target_metric",
383398
"kube_horizontalpodautoscaler_status_current_replicas",
384399
"kube_horizontalpodautoscaler_status_desired_replicas",
385400
"kube_horizontalpodautoscaler_status_condition",

0 commit comments

Comments
 (0)