Skip to content

Commit c2f144c

Browse files
authored
add component metrics (#292)
1 parent 86574f7 commit c2f144c

File tree

4 files changed

+79
-15
lines changed

4 files changed

+79
-15
lines changed

go.sum

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -228,30 +228,18 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
228228
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
229229
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
230230
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
231-
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
232-
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
233231
k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw=
234232
k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw=
235-
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
236-
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
237233
k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
238234
k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
239-
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
240-
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
241235
k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
242236
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
243-
k8s.io/cli-runtime v0.33.0 h1:Lbl/pq/1o8BaIuyn+aVLdEPHVN665tBAXUePs8wjX7c=
244-
k8s.io/cli-runtime v0.33.0/go.mod h1:QcA+r43HeUM9jXFJx7A+yiTPfCooau/iCcP1wQh4NFw=
245237
k8s.io/cli-runtime v0.33.1 h1:TvpjEtF71ViFmPeYMj1baZMJR4iWUEplklsUQ7D3quA=
246238
k8s.io/cli-runtime v0.33.1/go.mod h1:9dz5Q4Uh8io4OWCLiEf/217DXwqNgiTS/IOuza99VZE=
247-
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
248-
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
249239
k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
250240
k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA=
251241
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
252242
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
253-
k8s.io/kube-aggregator v0.33.0 h1:jTjEe/DqpJcaPp4x1CjNaMb1XPD+H8SSf/yVpC8coFg=
254-
k8s.io/kube-aggregator v0.33.0/go.mod h1:6BRnSnWzh6nWUxjQhNwGP9gMnPfSW0WsFeOZGMHtvZw=
255243
k8s.io/kube-aggregator v0.33.1 h1:PigQUqAvd6Y4hBjQAqhKz3lEJC2VHLL4bSOEuS06a40=
256244
k8s.io/kube-aggregator v0.33.1/go.mod h1:16/wlU5Lj7hNJSv7JSu5FLvxyrgiJVLCHzfVoECAsuI=
257245
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
@@ -260,8 +248,6 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6J
260248
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
261249
sigs.k8s.io/cli-utils v0.37.2 h1:GOfKw5RV2HDQZDJlru5KkfLO1tbxqMoyn1IYUxqBpNg=
262250
sigs.k8s.io/cli-utils v0.37.2/go.mod h1:V+IZZr4UoGj7gMJXklWBg6t5xbdThFBcpj4MrZuCYco=
263-
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
264-
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
265251
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
266252
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
267253
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=

internal/metrics/metrics.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,27 @@ var (
5858
},
5959
[]string{"controller"},
6060
)
61+
ComponentState = prometheus.NewGaugeVec(
62+
prometheus.GaugeOpts{
63+
Name: prefix + "_component_state",
64+
Help: "Current state of a component",
65+
},
66+
[]string{"controller", "group", "kind", "namespace", "name", "state"},
67+
)
68+
Dependents = prometheus.NewGaugeVec(
69+
prometheus.GaugeOpts{
70+
Name: prefix + "_dependents_total",
71+
Help: "Number of dependent objects",
72+
},
73+
[]string{"controller", "group", "kind", "namespace", "name"},
74+
)
75+
UnreadyDependents = prometheus.NewGaugeVec(
76+
prometheus.GaugeOpts{
77+
Name: prefix + "_unready_dependents_total",
78+
Help: "Number of unready dependent objects",
79+
},
80+
[]string{"controller", "group", "kind", "namespace", "name"},
81+
)
6182
)
6283

6384
func init() {
@@ -68,5 +89,8 @@ func init() {
6889
Operations,
6990
CreatedClients,
7091
ActiveClients,
92+
ComponentState,
93+
Dependents,
94+
UnreadyDependents,
7195
)
7296
}

pkg/component/reconciler.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,57 @@ func (r *Reconciler[T]) Reconcile(ctx context.Context, req ctrl.Request) (result
355355
}
356356
}
357357

358-
// TODO: it seems that no events will be written if the component's namespace is in deletion
359358
// TODO: do not use GetState(); but accessing the condition directly is not safe (see caveat remark on the
360359
// getCondition() and getOrAddCondition() methods)
361360
state, reason, message := status.GetState()
361+
362+
if component.GetDeletionTimestamp().IsZero() || controllerutil.ContainsFinalizer(component, *r.options.Finalizer) {
363+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
364+
component.GetNamespace(), component.GetName(), string(StateReady)).
365+
Set(float64(boolToInt(state == StateReady)))
366+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
367+
component.GetNamespace(), component.GetName(), string(StatePending)).
368+
Set(float64(boolToInt(state == StatePending)))
369+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
370+
component.GetNamespace(), component.GetName(), string(StateProcessing)).
371+
Set(float64(boolToInt(state == StateProcessing)))
372+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
373+
component.GetNamespace(), component.GetName(), string(StateDeletionPending)).
374+
Set(float64(boolToInt(state == StateDeletionPending)))
375+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
376+
component.GetNamespace(), component.GetName(), string(StateDeleting)).
377+
Set(float64(boolToInt(state == StateDeleting)))
378+
metrics.ComponentState.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
379+
component.GetNamespace(), component.GetName(), string(StateError)).
380+
Set(float64(boolToInt(state == StateError)))
381+
metrics.Dependents.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
382+
component.GetNamespace(), component.GetName()).
383+
Set(float64(len(status.Inventory)))
384+
metrics.UnreadyDependents.WithLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
385+
component.GetNamespace(), component.GetName()).
386+
Set(float64(slices.Count(status.Inventory, func(item *reconciler.InventoryItem) bool {
387+
return item.Phase != reconciler.PhaseReady && item.Phase != reconciler.PhaseCompleted
388+
})))
389+
} else {
390+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
391+
component.GetNamespace(), component.GetName(), string(StateReady))
392+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
393+
component.GetNamespace(), component.GetName(), string(StatePending))
394+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
395+
component.GetNamespace(), component.GetName(), string(StateProcessing))
396+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
397+
component.GetNamespace(), component.GetName(), string(StateDeletionPending))
398+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
399+
component.GetNamespace(), component.GetName(), string(StateDeleting))
400+
metrics.ComponentState.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
401+
component.GetNamespace(), component.GetName(), string(StateError))
402+
metrics.Dependents.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
403+
component.GetNamespace(), component.GetName())
404+
metrics.UnreadyDependents.DeleteLabelValues(r.controllerName, component.GetObjectKind().GroupVersionKind().Group, component.GetObjectKind().GroupVersionKind().Kind,
405+
component.GetNamespace(), component.GetName())
406+
}
407+
408+
// TODO: it seems that no events will be written if the component's namespace is in deletion
362409
var eventAnnotations map[string]string
363410
// TODO: formalize this into a real published interface
364411
// TODO: pass previousState, and especially componentDigest in a better way;

pkg/component/util.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,10 @@ func addJitter(d *time.Duration, minPercent int, maxPercent int) {
5252
max := int64(maxPercent)
5353
*d = *d + time.Duration((rand.Int63n(max-min+1)+min)*int64(*d)/100)
5454
}
55+
56+
func boolToInt(b bool) int {
57+
if b {
58+
return 1
59+
}
60+
return 0
61+
}

0 commit comments

Comments
 (0)