Skip to content

Commit 72306e8

Browse files
committed
✨ added reconciles_total metric
1 parent 43351af commit 72306e8

File tree

4 files changed

+70
-16
lines changed

4 files changed

+70
-16
lines changed

pkg/controller/controller.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ func New(name string, mgr manager.Manager, options Options) (Controller, error)
7878

7979
// Create controller with dependencies set
8080
c := &controller.Controller{
81-
Do: options.Reconciler,
82-
Cache: mgr.GetCache(),
83-
Config: mgr.GetConfig(),
84-
Scheme: mgr.GetScheme(),
85-
Client: mgr.GetClient(),
86-
Recorder: mgr.GetRecorder(name),
87-
Queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), name),
81+
Do: options.Reconciler,
82+
Cache: mgr.GetCache(),
83+
Config: mgr.GetConfig(),
84+
Scheme: mgr.GetScheme(),
85+
Client: mgr.GetClient(),
86+
Recorder: mgr.GetRecorder(name),
87+
Queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), name),
8888
MaxConcurrentReconciles: options.MaxConcurrentReconciles,
89-
Name: name,
89+
Name: name,
9090
}
9191

9292
// Add the controller as a Manager components

pkg/internal/controller/controller.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,15 @@ func (c *Controller) processNextWorkItem() bool {
214214
c.Queue.AddRateLimited(req)
215215
log.Error(err, "Reconciler error", "controller", c.Name, "request", req)
216216
ctrlmetrics.ReconcileErrors.WithLabelValues(c.Name).Inc()
217-
217+
ctrlmetrics.ReconcileTotal.WithLabelValues(c.Name, "error").Inc()
218218
return false
219219
} else if result.RequeueAfter > 0 {
220220
c.Queue.AddAfter(req, result.RequeueAfter)
221+
ctrlmetrics.ReconcileTotal.WithLabelValues(c.Name, "requeue_after").Inc()
221222
return true
222223
} else if result.Requeue {
223224
c.Queue.AddRateLimited(req)
225+
ctrlmetrics.ReconcileTotal.WithLabelValues(c.Name, "requeue").Inc()
224226
return true
225227
}
226228

@@ -231,6 +233,7 @@ func (c *Controller) processNextWorkItem() bool {
231233
// TODO(directxman12): What does 1 mean? Do we want level constants? Do we want levels at all?
232234
log.V(1).Info("Successfully Reconciled", "controller", c.Name, "request", req)
233235

236+
ctrlmetrics.ReconcileTotal.WithLabelValues(c.Name, "success").Inc()
234237
// Return true, don't take a break
235238
return true
236239
}

pkg/internal/controller/controller_test.go

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ var _ = Describe("controller", func() {
6363
informers = &informertest.FakeInformers{}
6464
ctrl = &Controller{
6565
MaxConcurrentReconciles: 1,
66-
Do: fakeReconcile,
67-
Queue: queue,
68-
Cache: informers,
66+
Do: fakeReconcile,
67+
Queue: queue,
68+
Cache: informers,
6969
}
7070
ctrl.InjectFunc(func(interface{}) error { return nil })
7171
})
@@ -410,12 +410,12 @@ var _ = Describe("controller", func() {
410410

411411
Context("should update prometheus metrics", func() {
412412
It("should requeue a Request if there is an error and continue processing items", func(done Done) {
413-
var queueLength, reconcileErrs dto.Metric
413+
var queueLength, reconcileErrs, reconcileTotal dto.Metric
414414
ctrlmetrics.QueueLength.Reset()
415415
Expect(func() error {
416416
ctrlmetrics.QueueLength.WithLabelValues(ctrl.Name).Write(&queueLength)
417417
if queueLength.GetGauge().GetValue() != 0.0 {
418-
return fmt.Errorf("metrics not reset")
418+
return fmt.Errorf("metric queue length not reset")
419419
}
420420
return nil
421421
}()).Should(Succeed())
@@ -424,7 +424,24 @@ var _ = Describe("controller", func() {
424424
Expect(func() error {
425425
ctrlmetrics.ReconcileErrors.WithLabelValues(ctrl.Name).Write(&reconcileErrs)
426426
if reconcileErrs.GetCounter().GetValue() != 0.0 {
427-
return fmt.Errorf("metrics not reset")
427+
return fmt.Errorf("metric reconcile errors not reset")
428+
}
429+
return nil
430+
}()).Should(Succeed())
431+
432+
ctrlmetrics.ReconcileTotal.Reset()
433+
Expect(func() error {
434+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "success").Write(&reconcileTotal)
435+
if reconcileTotal.GetCounter().GetValue() != 0.0 {
436+
return fmt.Errorf("metric reconcile total with label success not reset")
437+
}
438+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "error").Write(&reconcileTotal)
439+
if reconcileTotal.GetCounter().GetValue() != 0.0 {
440+
return fmt.Errorf("metric reconcile total with label error not reset")
441+
}
442+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "retry").Write(&reconcileTotal)
443+
if reconcileTotal.GetCounter().GetValue() != 0.0 {
444+
return fmt.Errorf("metric reconcile total with label retry not reset")
428445
}
429446
return nil
430447
}()).Should(Succeed())
@@ -444,7 +461,7 @@ var _ = Describe("controller", func() {
444461
Eventually(func() error {
445462
ctrlmetrics.QueueLength.WithLabelValues(ctrl.Name).Write(&queueLength)
446463
if queueLength.GetGauge().GetValue() != 1.0 {
447-
return fmt.Errorf("metrics not updated")
464+
return fmt.Errorf("metric queue length not updated")
448465
}
449466
return nil
450467
}, 2.0).Should(Succeed())
@@ -455,6 +472,13 @@ var _ = Describe("controller", func() {
455472
}
456473
return nil
457474
}, 2.0).Should(Succeed())
475+
Eventually(func() error {
476+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "error").Write(&reconcileTotal)
477+
if reconcileTotal.GetCounter().GetValue() != 1.0 {
478+
return fmt.Errorf("metric reconcile total not updated")
479+
}
480+
return nil
481+
}, 2.0).Should(Succeed())
458482

459483
By("Invoking Reconciler a second time without error")
460484
fakeReconcile.Err = nil
@@ -464,6 +488,23 @@ var _ = Describe("controller", func() {
464488
Eventually(ctrl.Queue.Len).Should(Equal(0))
465489
Eventually(func() int { return ctrl.Queue.NumRequeues(request) }).Should(Equal(0))
466490

491+
By("Examining ReconcileTotal post second reconcile")
492+
Eventually(func() error {
493+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "error").Write(&reconcileTotal)
494+
if reconcileTotal.GetCounter().GetValue() != 1.0 {
495+
return fmt.Errorf("metric reconcile total with label error not updated")
496+
}
497+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "success").Write(&reconcileTotal)
498+
if reconcileTotal.GetCounter().GetValue() != 1.0 {
499+
return fmt.Errorf("metric reconcile total with label success not updated")
500+
}
501+
ctrlmetrics.ReconcileTotal.WithLabelValues(ctrl.Name, "retry").Write(&reconcileTotal)
502+
if reconcileTotal.GetCounter().GetValue() != 0.0 {
503+
return fmt.Errorf("metric reconcile total with label error was updated")
504+
}
505+
return nil
506+
}, 2.0).Should(Succeed())
507+
467508
close(done)
468509
}, 2.0)
469510

pkg/internal/controller/metrics/metrics.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ var (
2929
Help: "Length of reconcile queue per controller",
3030
}, []string{"controller"})
3131

32+
// ReconcileTotal is a prometheus counter metrics which holds the total
33+
// number of reconciles per controller. It has two labels. controller label refers
34+
// to the controller name and result label refers to the reconcile result i.e
35+
// success, error, requeue, requeue_after.
36+
ReconcileTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
37+
Name: "controller_runtime_reconcile_total",
38+
Help: "Total number of reconciles per controller",
39+
}, []string{"controller", "result"})
40+
3241
// ReconcileErrors is a prometheus counter metrics which holds the total
3342
// number of errors from the Reconciler
3443
ReconcileErrors = prometheus.NewCounterVec(prometheus.CounterOpts{
@@ -47,6 +56,7 @@ var (
4756
func init() {
4857
metrics.Registry.MustRegister(
4958
QueueLength,
59+
ReconcileTotal,
5060
ReconcileErrors,
5161
ReconcileTime,
5262
// expose process metrics like CPU, Memory, file descriptor usage etc.

0 commit comments

Comments
 (0)