Skip to content

Commit 16e810a

Browse files
committed
Record metrics for readiness and duration
Using the conventions of the day. Signed-off-by: Michael Bridgen <[email protected]>
1 parent 027370a commit 16e810a

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

controllers/imageupdateautomation_controller.go

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ import (
3333
"github.com/go-git/go-git/v5/plumbing/transport"
3434
"github.com/go-logr/logr"
3535
corev1 "k8s.io/api/core/v1"
36+
apimeta "k8s.io/apimachinery/pkg/api/meta"
3637
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3738
"k8s.io/apimachinery/pkg/runtime"
3839
"k8s.io/apimachinery/pkg/types"
3940
kuberecorder "k8s.io/client-go/tools/record"
41+
"k8s.io/client-go/tools/reference"
4042
ctrl "sigs.k8s.io/controller-runtime"
4143
"sigs.k8s.io/controller-runtime/pkg/client"
4244
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -46,6 +48,7 @@ import (
4648
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
4749
"github.com/fluxcd/pkg/apis/meta"
4850
"github.com/fluxcd/pkg/runtime/events"
51+
"github.com/fluxcd/pkg/runtime/metrics"
4952
"github.com/fluxcd/pkg/runtime/predicates"
5053
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
5154
"github.com/fluxcd/source-controller/pkg/git"
@@ -68,9 +71,10 @@ const imagePolicyKey = ".spec.update.imagePolicy"
6871
// ImageUpdateAutomationReconciler reconciles a ImageUpdateAutomation object
6972
type ImageUpdateAutomationReconciler struct {
7073
client.Client
71-
Log logr.Logger
72-
Scheme *runtime.Scheme
73-
EventRecorder kuberecorder.EventRecorder
74+
Log logr.Logger
75+
Scheme *runtime.Scheme
76+
EventRecorder kuberecorder.EventRecorder
77+
MetricsRecorder *metrics.Recorder
7478
}
7579

7680
// +kubebuilder:rbac:groups=image.toolkit.fluxcd.io,resources=imageupdateautomations,verbs=get;list;watch;create;update;patch;delete
@@ -92,6 +96,19 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(req ctrl.Request) (ctrl.Resu
9296
return ctrl.Result{}, nil
9397
}
9498

99+
// Record readiness metric when exiting; if there's any points at
100+
// which the readiness is updated _without also exiting_, they
101+
// should also record the readiness.
102+
defer r.recordReadinessMetric(&auto)
103+
// Record reconciliation duration when exiting
104+
if r.MetricsRecorder != nil {
105+
objRef, err := reference.GetReference(r.Scheme, &auto)
106+
if err != nil {
107+
return ctrl.Result{}, err
108+
}
109+
defer r.MetricsRecorder.RecordDuration(*objRef, now)
110+
}
111+
95112
// whatever else happens, we've now "seen" the reconcile
96113
// annotation if it's there
97114
if token, ok := meta.ReconcileAnnotationValue(auto.GetAnnotations()); ok {
@@ -359,14 +376,37 @@ func commitAllAndPush(ctx context.Context, repo *gogit.Repository, access repoAc
359376
})
360377
}
361378

362-
// --- events
379+
// --- events, metrics
363380

364381
func (r *ImageUpdateAutomationReconciler) event(auto imagev1.ImageUpdateAutomation, severity, msg string) {
365382
if r.EventRecorder != nil {
366383
r.EventRecorder.Event(&auto, "Normal", severity, msg)
367384
}
368385
}
369386

387+
func (r *ImageUpdateAutomationReconciler) recordReadinessMetric(auto *imagev1.ImageUpdateAutomation) {
388+
if r.MetricsRecorder == nil {
389+
return
390+
}
391+
392+
objRef, err := reference.GetReference(r.Scheme, auto)
393+
if err != nil {
394+
r.Log.WithValues(
395+
strings.ToLower(auto.Kind),
396+
fmt.Sprintf("%s/%s", auto.GetNamespace(), auto.GetName()),
397+
).Error(err, "unable to record readiness metric")
398+
return
399+
}
400+
if rc := apimeta.FindStatusCondition(auto.Status.Conditions, meta.ReadyCondition); rc != nil {
401+
r.MetricsRecorder.RecordCondition(*objRef, *rc, !auto.DeletionTimestamp.IsZero())
402+
} else {
403+
r.MetricsRecorder.RecordCondition(*objRef, metav1.Condition{
404+
Type: meta.ReadyCondition,
405+
Status: metav1.ConditionUnknown,
406+
}, !auto.DeletionTimestamp.IsZero())
407+
}
408+
}
409+
370410
// --- updates
371411

372412
// updateAccordingToSetters updates files under the root by treating

main.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import (
2525
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
2626
ctrl "sigs.k8s.io/controller-runtime"
2727
"sigs.k8s.io/controller-runtime/pkg/healthz"
28+
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
2829

2930
imagev1alpha1_reflect "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
3031
"github.com/fluxcd/pkg/runtime/logger"
32+
"github.com/fluxcd/pkg/runtime/metrics"
3133
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
3234

3335
imagev1alpha1_auto "github.com/fluxcd/image-automation-controller/api/v1alpha1"
@@ -72,6 +74,9 @@ func main() {
7274

7375
ctrl.SetLogger(logger.NewLogger(logLevel, logJSON))
7476

77+
metricsRecorder := metrics.NewRecorder()
78+
ctrlmetrics.Registry.MustRegister(metricsRecorder.Collectors()...)
79+
7580
watchNamespace := ""
7681
if !watchAllNamespaces {
7782
watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
@@ -94,10 +99,11 @@ func main() {
9499
setupChecks(mgr)
95100

96101
if err = (&controllers.ImageUpdateAutomationReconciler{
97-
Client: mgr.GetClient(),
98-
Log: ctrl.Log.WithName("controllers").WithName("ImageUpdateAutomation"),
99-
Scheme: mgr.GetScheme(),
100-
EventRecorder: mgr.GetEventRecorderFor("image-automation-controller"),
102+
Client: mgr.GetClient(),
103+
Log: ctrl.Log.WithName("controllers").WithName("ImageUpdateAutomation"),
104+
Scheme: mgr.GetScheme(),
105+
EventRecorder: mgr.GetEventRecorderFor("image-automation-controller"),
106+
MetricsRecorder: metricsRecorder,
101107
}).SetupWithManager(mgr); err != nil {
102108
setupLog.Error(err, "unable to create controller", "controller", "ImageUpdateAutomation")
103109
os.Exit(1)

0 commit comments

Comments
 (0)