Skip to content

Commit c96cd17

Browse files
authored
Merge pull request #2 from sourcehawk/feature/optional-extra-labels-for-gauge
enble optional extra labels to the gauge
2 parents d45c797 + 171dbb0 commit c96cd17

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ func (r *MyReconciler) SetStatusCondition(cr *v1.MyCR, cond metav1.Condition) bo
189189
updated := meta.FindStatusCondition(cr.Status.Conditions, cond.Type)
190190
if updated != nil {
191191
r.Recorder.RecordConditionFor(
192-
kind, cr, updated.Type, string(updated.Status), updated.Reason, updated.LastTransitionTime,
192+
kind, cr, updated.Type,
193+
string(updated.Status), updated.Reason, updated.LastTransitionTime.Time,
193194
)
194195
}
195196
return changed

pkg/crd-condition-metrics/metrics.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const (
1616
var (
1717
indexLabels = []string{"controller", "kind", "name", "namespace"}
1818
groupLabels = []string{"condition"}
19-
extraLabels = []string{"status", "reason", "id"}
19+
infoLabels = []string{"status", "reason", "id"}
2020
)
2121

2222
type OperatorConditionsGauge struct {
@@ -32,7 +32,7 @@ type OperatorConditionsGauge struct {
3232
// OperatorConditionsGauge = NewOperatorConditionsGauge("my-operator")
3333
// controllermetrics.Registry.MustRegister(OperatorConditionsGauge)
3434
// }
35-
func NewOperatorConditionsGauge(metricNamespace string) *OperatorConditionsGauge {
35+
func NewOperatorConditionsGauge(metricNamespace string, extraLabels ...string) *OperatorConditionsGauge {
3636
return &OperatorConditionsGauge{
3737
metrics.NewGaugeVecSet(
3838
metricNamespace,
@@ -41,7 +41,7 @@ func NewOperatorConditionsGauge(metricNamespace string) *OperatorConditionsGauge
4141
operatorConditionMetricHelp,
4242
indexLabels,
4343
groupLabels,
44-
extraLabels...,
44+
append(infoLabels, extraLabels...)...,
4545
),
4646
}
4747
}
@@ -93,11 +93,13 @@ type ConditionMetricRecorder struct {
9393
func (r *ConditionMetricRecorder) RecordConditionFor(
9494
kind string, object ObjectLike,
9595
conditionType, conditionStatus, conditionReason string, lastTransitionTime time.Time,
96+
extraLabelValues ...string,
9697
) {
9798
id := fmt.Sprintf("%s/%s", object.GetNamespace(), object.GetName())
9899
indexValues := []string{r.Controller, kind, object.GetName(), object.GetNamespace()}
99100
groupValues := []string{conditionType}
100101
extraValues := []string{conditionStatus, conditionReason, id}
102+
extraValues = append(extraValues, extraLabelValues...)
101103

102104
if lastTransitionTime.IsZero() {
103105
lastTransitionTime = time.Now().UTC()

pkg/crd-condition-metrics/metrics_test.go

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ func makeObj(name, namespace string) *FakeObject {
1818
}
1919
}
2020

21-
func TestConditionMetricRecorder_Record_Transition_And_SecondCondition(t *testing.T) {
21+
const (
22+
kind = "MyCRD"
23+
)
24+
25+
func TestConditionMetricRecorder_RecordConditionFor(t *testing.T) {
2226
gauge := NewOperatorConditionsGauge("test_record_transition_and_second_condition")
2327
reg := prometheus.NewRegistry()
2428
_ = reg.Register(gauge)
@@ -28,7 +32,6 @@ func TestConditionMetricRecorder_Record_Transition_And_SecondCondition(t *testin
2832
Controller: "my-controller",
2933
OperatorConditionsGauge: gauge,
3034
}
31-
kind := "MyCRD"
3235
name := "cr-1"
3336
ns := "prod"
3437
transitionTime := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)
@@ -63,6 +66,52 @@ test_record_transition_and_second_condition_controller_condition{condition="Sync
6366
assert.Equal(t, 2, removed)
6467
}
6568

69+
func TestConditionMetricRecorder_RecordConditionFor_WithExtraLabels(t *testing.T) {
70+
gauge := NewOperatorConditionsGauge(
71+
"test_record_transition_and_second_condition", "zz_extra",
72+
)
73+
reg := prometheus.NewRegistry()
74+
_ = reg.Register(gauge)
75+
76+
// Arrange
77+
rec := &ConditionMetricRecorder{
78+
Controller: "my-controller",
79+
OperatorConditionsGauge: gauge,
80+
}
81+
name := "cr-1"
82+
ns := "prod"
83+
transitionTime := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)
84+
85+
obj := makeObj(name, ns)
86+
87+
// Record Ready=True
88+
rec.RecordConditionFor(kind, obj, "Ready", "True", "", transitionTime, "extra")
89+
90+
// Flip Ready -> False with reason
91+
rec.RecordConditionFor(kind, obj, "Ready", "False", "Failed", transitionTime, "extra")
92+
93+
// Another condition Synchronized=True (independent group)
94+
rec.RecordConditionFor(kind, obj, "Synchronized", "True", "", transitionTime, "extra")
95+
96+
// Expect: Ready False(reason)=1, Synchronized True=1
97+
want := `
98+
# HELP test_record_transition_and_second_condition_controller_condition Condition status for a custom resource; one time series per (custom resource, condition type) combination.
99+
# TYPE test_record_transition_and_second_condition_controller_condition gauge
100+
test_record_transition_and_second_condition_controller_condition{condition="Ready",controller="my-controller",id="prod/cr-1",kind="MyCRD",name="cr-1",namespace="prod",reason="Failed",status="False",zz_extra="extra"} 1735689600
101+
test_record_transition_and_second_condition_controller_condition{condition="Synchronized",controller="my-controller",id="prod/cr-1",kind="MyCRD",name="cr-1",namespace="prod",reason="",status="True",zz_extra="extra"} 1735689600
102+
`
103+
require.NoError(t,
104+
testutil.GatherAndCompare(
105+
reg,
106+
strings.NewReader(want),
107+
"test_record_transition_and_second_condition_controller_condition",
108+
),
109+
)
110+
111+
removed := rec.RemoveConditionsFor(kind, obj)
112+
assert.Equal(t, 2, removed)
113+
}
114+
66115
func TestConditionMetricRecorder_RemoveConditionsFor(t *testing.T) {
67116
gauge := NewOperatorConditionsGauge("test_remove_conditions_for_condition")
68117
reg := prometheus.NewRegistry()
@@ -72,7 +121,6 @@ func TestConditionMetricRecorder_RemoveConditionsFor(t *testing.T) {
72121
Controller: "my-controller",
73122
OperatorConditionsGauge: gauge,
74123
}
75-
kind := "MyCRD"
76124
name := "cr-2"
77125
ns := "staging"
78126
transitionTime := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)

0 commit comments

Comments
 (0)