@@ -23,6 +23,8 @@ import (
23
23
24
24
. "github.com/onsi/ginkgo"
25
25
. "github.com/onsi/gomega"
26
+ "github.com/prometheus/client_golang/prometheus"
27
+ dto "github.com/prometheus/client_model/go"
26
28
"k8s.io/api/apps/v1"
27
29
corev1 "k8s.io/api/core/v1"
28
30
"k8s.io/apimachinery/pkg/types"
@@ -31,6 +33,7 @@ import (
31
33
"sigs.k8s.io/controller-runtime/pkg/cache/informertest"
32
34
"sigs.k8s.io/controller-runtime/pkg/controller/controllertest"
33
35
"sigs.k8s.io/controller-runtime/pkg/handler"
36
+ ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/internal/controller/metrics"
34
37
"sigs.k8s.io/controller-runtime/pkg/predicate"
35
38
"sigs.k8s.io/controller-runtime/pkg/reconcile"
36
39
"sigs.k8s.io/controller-runtime/pkg/reconcile/reconciletest"
@@ -404,6 +407,90 @@ var _ = Describe("controller", func() {
404
407
It ("should create a new go routine for MaxConcurrentReconciles" , func () {
405
408
// TODO(community): write this test
406
409
})
410
+
411
+ Context ("should update prometheus metrics" , func () {
412
+ It ("should requeue a Request if there is an error and continue processing items" , func (done Done ) {
413
+ ctrlmetrics .QueueLength = prometheus .NewGaugeVec (prometheus.GaugeOpts {
414
+ Name : "controller_runtime_reconcile_queue_length" ,
415
+ Help : "Length of reconcile queue per controller" ,
416
+ }, []string {"controller" })
417
+ ctrlmetrics .ReconcileErrors = prometheus .NewCounterVec (prometheus.CounterOpts {
418
+ Name : "controller_runtime_reconcile_errors_total" ,
419
+ Help : "Total number of reconcile errors per controller" ,
420
+ }, []string {"controller" })
421
+
422
+ fakeReconcile .Err = fmt .Errorf ("expected error: reconcile" )
423
+ go func () {
424
+ defer GinkgoRecover ()
425
+ Expect (ctrl .Start (stop )).NotTo (HaveOccurred ())
426
+ }()
427
+ ctrl .Queue .Add (request )
428
+
429
+ // Reduce the jitterperiod so we don't have to wait a second before the reconcile function is rerun.
430
+ ctrl .JitterPeriod = time .Millisecond
431
+
432
+ By ("Invoking Reconciler which will give an error" )
433
+ Expect (<- reconciled ).To (Equal (request ))
434
+ var queueLength , reconcileErrs dto.Metric
435
+ Eventually (func () error {
436
+ ctrlmetrics .QueueLength .WithLabelValues (ctrl .Name ).Write (& queueLength )
437
+ if queueLength .GetGauge ().GetValue () != 1.0 {
438
+ return fmt .Errorf ("metrics not updated" )
439
+ }
440
+ return nil
441
+ }, 2.0 ).Should (Succeed ())
442
+ Eventually (func () error {
443
+ ctrlmetrics .ReconcileErrors .WithLabelValues (ctrl .Name ).Write (& reconcileErrs )
444
+ if reconcileErrs .GetCounter ().GetValue () != 1.0 {
445
+ return fmt .Errorf ("metrics not updated" )
446
+ }
447
+ return nil
448
+ }, 2.0 ).Should (Succeed ())
449
+
450
+ By ("Invoking Reconciler a second time without error" )
451
+ fakeReconcile .Err = nil
452
+ Expect (<- reconciled ).To (Equal (request ))
453
+
454
+ By ("Removing the item from the queue" )
455
+ Eventually (ctrl .Queue .Len ).Should (Equal (0 ))
456
+ Eventually (func () int { return ctrl .Queue .NumRequeues (request ) }).Should (Equal (0 ))
457
+
458
+ close (done )
459
+ }, 2.0 )
460
+
461
+ It ("should add a reconcile time to the reconcile time histogram" , func (done Done ) {
462
+ ctrlmetrics .ReconcileTime = prometheus .NewHistogramVec (prometheus.HistogramOpts {
463
+ Name : "controller_runtime_reconcile_time_second" ,
464
+ Help : "Length of time per reconcile per controller" ,
465
+ }, []string {"controller" })
466
+
467
+ go func () {
468
+ defer GinkgoRecover ()
469
+ Expect (ctrl .Start (stop )).NotTo (HaveOccurred ())
470
+ }()
471
+ ctrl .Queue .Add (request )
472
+
473
+ By ("Invoking Reconciler" )
474
+ Expect (<- reconciled ).To (Equal (request ))
475
+
476
+ By ("Removing the item from the queue" )
477
+ Eventually (ctrl .Queue .Len ).Should (Equal (0 ))
478
+ Eventually (func () int { return ctrl .Queue .NumRequeues (request ) }).Should (Equal (0 ))
479
+
480
+ var reconcileTime dto.Metric
481
+ Eventually (func () error {
482
+ histObserver := ctrlmetrics .ReconcileTime .WithLabelValues (ctrl .Name )
483
+ hist := histObserver .(prometheus.Histogram )
484
+ hist .Write (& reconcileTime )
485
+ if reconcileTime .GetHistogram ().GetSampleCount () != uint64 (1 ) {
486
+ return fmt .Errorf ("metrics not updated" )
487
+ }
488
+ return nil
489
+ }, 2.0 ).Should (Succeed ())
490
+
491
+ close (done )
492
+ }, 4.0 )
493
+ })
407
494
})
408
495
})
409
496
0 commit comments