Skip to content

Commit f562c7d

Browse files
authored
fix: delete deprecated metrics (#162)
* fix: delete deprecated metrics * fix: update tests * fix: only pass additional labels when they have changed to the delete call * fix: Added comment to explain the conditional addition of additional labels * fix: address nits and fix breaking test
1 parent 2e83f73 commit f562c7d

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

status/controller.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,20 +276,24 @@ func (c *Controller[T]) reconcile(ctx context.Context, req reconcile.Request, o
276276

277277
for _, observedCondition := range observedConditions.List() {
278278
if currentCondition := currentConditions.Get(observedCondition.Type); currentCondition == nil || currentCondition.Status != observedCondition.Status || currentCondition.Reason != observedCondition.Reason || !maps.Equal(c.toAdditionalGaugeMetricLabels(o), observedGaugeLabels) {
279+
// We want to check if the additional labels on the object has changed, and if so, delete the metrics with the old labels.
280+
// Because we add the additional labels to the deletePartialMatchGaugeMetric() call based on if they have changed, it will not delete
281+
// the deprecated metrics when the additional labels change but only when there is a change in the condition status because
282+
// deprecated metrics to do not have the additional labels.
279283
c.deletePartialMatchGaugeMetric(c.ConditionCount, ConditionCount, lo.Assign(map[string]string{
280284
MetricLabelNamespace: req.Namespace,
281285
MetricLabelName: req.Name,
282286
pmetrics.LabelType: observedCondition.Type,
283287
MetricLabelConditionStatus: string(observedCondition.Status),
284288
pmetrics.LabelReason: observedCondition.Reason,
285-
}, observedGaugeLabels))
289+
}, lo.Ternary(!maps.Equal(c.toAdditionalGaugeMetricLabels(o), observedGaugeLabels), observedGaugeLabels, nil)))
286290
c.deletePartialMatchGaugeMetric(c.ConditionCurrentStatusSeconds, ConditionCurrentStatusSeconds, lo.Assign(map[string]string{
287291
MetricLabelNamespace: req.Namespace,
288292
MetricLabelName: req.Name,
289293
pmetrics.LabelType: observedCondition.Type,
290294
MetricLabelConditionStatus: string(observedCondition.Status),
291295
pmetrics.LabelReason: observedCondition.Reason,
292-
}, observedGaugeLabels))
296+
}, lo.Ternary(!maps.Equal(c.toAdditionalGaugeMetricLabels(o), observedGaugeLabels), observedGaugeLabels, nil)))
293297
}
294298
}
295299

status/controller_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,8 @@ var _ = Describe("Controller", func() {
621621
})
622622
It("should ensure that we don't leak metrics when changing labels", func() {
623623
metrics.Registry = prometheus.NewRegistry()
624+
metrics.Registry.Register(status.ConditionCount.(*pmetrics.PrometheusGauge).GaugeVec)
625+
metrics.Registry.Register(status.ConditionCurrentStatusSeconds.(*pmetrics.PrometheusGauge).GaugeVec)
624626
testObject := test.Object(&test.CustomObject{
625627
ObjectMeta: metav1.ObjectMeta{
626628
Labels: map[string]string{
@@ -635,7 +637,7 @@ var _ = Describe("Controller", func() {
635637
})
636638
ExpectApplied(ctx, kubeClient, testObject)
637639

638-
controller = status.NewController[*test.CustomObject](kubeClient, recorder, status.WithLabels("operator.pkg/key1", "operator.pkg/key2", "operator.pkg/key3"))
640+
controller = status.NewController[*test.CustomObject](kubeClient, recorder, status.WithLabels("operator.pkg/key1", "operator.pkg/key2", "operator.pkg/key3"), status.EmitDeprecatedMetrics)
639641
ExpectReconciled(ctx, controller, testObject)
640642

641643
Expect(GetMetric("operator_customobject_status_condition_count", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionTrue), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": ""}))).To(BeNil())
@@ -645,6 +647,9 @@ var _ = Describe("Controller", func() {
645647
Expect(GetMetric("operator_customobject_status_condition_current_status_seconds", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionFalse), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": ""}))).To(BeNil())
646648
Expect(GetMetric("operator_customobject_status_condition_current_status_seconds", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": ""})).GetGauge().GetValue()).ToNot(BeZero())
647649

650+
Expect(GetMetric("operator_status_condition_count", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).To(BeEquivalentTo(1))
651+
Expect(GetMetric("operator_status_condition_current_status_seconds", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).ToNot(BeZero())
652+
648653
// Set empty label to a different value and ensure that we don't still keep track of the old metric
649654
testObject.Labels["operator.pkg/key3"] = "value3"
650655

@@ -660,6 +665,17 @@ var _ = Describe("Controller", func() {
660665
Expect(GetMetric("operator_customobject_status_condition_current_status_seconds", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionFalse), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": "value3"}))).To(BeNil())
661666
Expect(GetMetric("operator_customobject_status_condition_current_status_seconds", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": ""})).GetGauge()).To(BeNil())
662667
Expect(GetMetric("operator_customobject_status_condition_current_status_seconds", lo.Assign(conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown), map[string]string{"operator_pkg_key1": "value1", "operator_pkg_key2": "value2", "operator_pkg_key3": "value3"})).GetGauge().GetValue()).ToNot(BeZero())
668+
669+
Expect(GetMetric("operator_status_condition_count", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).To(BeEquivalentTo(1))
670+
Expect(GetMetric("operator_status_condition_current_status_seconds", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).ToNot(BeZero())
671+
672+
testObject.StatusConditions().SetTrueWithReason(test.ConditionTypeFoo, "reason", "message")
673+
ExpectApplied(ctx, kubeClient, testObject)
674+
ExpectReconciled(ctx, controller, testObject)
675+
Expect(GetMetric("operator_status_condition_count", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).To(BeEquivalentTo(0))
676+
Expect(GetMetric("operator_status_condition_count", conditionLabels(test.ConditionTypeFoo, metav1.ConditionTrue)).GetGauge().GetValue()).To(BeEquivalentTo(1))
677+
Expect(GetMetric("operator_status_condition_current_status_seconds", conditionLabels(test.ConditionTypeFoo, metav1.ConditionUnknown)).GetGauge().GetValue()).To(BeZero())
678+
Expect(GetMetric("operator_status_condition_current_status_seconds", conditionLabels(test.ConditionTypeFoo, metav1.ConditionTrue)).GetGauge().GetValue()).ToNot(BeZero())
663679
})
664680
DescribeTable("should add labels to metrics", func(labelOption option.Function[status.Option], isGaugeOption bool) {
665681
metrics.Registry = prometheus.NewRegistry()

0 commit comments

Comments
 (0)