@@ -46,6 +46,7 @@ import (
4646
4747 "github.com/fluxcd/pkg/apis/meta"
4848 "github.com/fluxcd/pkg/runtime/events"
49+ "github.com/fluxcd/pkg/runtime/metrics"
4950 "github.com/fluxcd/pkg/runtime/predicates"
5051 sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
5152
@@ -63,6 +64,7 @@ type HelmReleaseReconciler struct {
6364 requeueDependency time.Duration
6465 EventRecorder kuberecorder.EventRecorder
6566 ExternalEventRecorder * events.Recorder
67+ MetricsRecorder * metrics.Recorder
6668}
6769
6870// ConditionError represents an error with a status condition reason attached.
@@ -111,7 +113,8 @@ func (r *HelmReleaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)
111113 // Return the error so we retry the failed garbage collection
112114 return ctrl.Result {}, err
113115 }
114-
116+ // Record deleted status
117+ r .recordReadiness (hr , true )
115118 // Remove our finalizer from the list and update it
116119 hr .ObjectMeta .Finalizers = removeString (hr .ObjectMeta .Finalizers , v2 .HelmReleaseFinalizer )
117120 if err := r .Update (ctx , & hr ); err != nil {
@@ -131,6 +134,9 @@ func (r *HelmReleaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)
131134 return ctrl.Result {Requeue : true }, updateStatusErr
132135 }
133136
137+ // Record ready status
138+ r .recordReadiness (hr , false )
139+
134140 // Log reconciliation duration
135141 durationMsg := fmt .Sprintf ("reconcilation finished in %s" , time .Now ().Sub (start ).String ())
136142 if result .RequeueAfter > 0 {
@@ -142,6 +148,7 @@ func (r *HelmReleaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)
142148}
143149
144150func (r * HelmReleaseReconciler ) reconcile (ctx context.Context , log logr.Logger , hr v2.HelmRelease ) (v2.HelmRelease , ctrl.Result , error ) {
151+ reconcileStart := time .Now ()
145152 // Record the value of the reconciliation request, if any
146153 if v , ok := hr .GetAnnotations ()[meta .ReconcileAtAnnotation ]; ok {
147154 hr .Status .LastHandledReconcileAt = v
@@ -155,6 +162,8 @@ func (r *HelmReleaseReconciler) reconcile(ctx context.Context, log logr.Logger,
155162 log .Error (updateStatusErr , "unable to update status after generation update" )
156163 return hr , ctrl.Result {Requeue : true }, updateStatusErr
157164 }
165+ // Record progressing status
166+ r .recordReadiness (hr , false )
158167 }
159168
160169 if hr .Spec .Suspend {
@@ -163,6 +172,15 @@ func (r *HelmReleaseReconciler) reconcile(ctx context.Context, log logr.Logger,
163172 return v2 .HelmReleaseNotReady (hr , meta .SuspendedReason , msg ), ctrl.Result {}, nil
164173 }
165174
175+ // record reconciliation duration
176+ if r .MetricsRecorder != nil {
177+ objRef , err := reference .GetReference (r .Scheme , & hr )
178+ if err != nil {
179+ return hr , ctrl.Result {Requeue : true }, err
180+ }
181+ defer r .MetricsRecorder .RecordDuration (* objRef , reconcileStart )
182+ }
183+
166184 // Reconcile chart based on the HelmChartTemplate
167185 hc , ok , reconcileErr := r .reconcileChart (ctx , & hr )
168186 if ! ok {
@@ -303,6 +321,8 @@ func (r *HelmReleaseReconciler) reconcileRelease(ctx context.Context, log logr.L
303321 log .Error (updateStatusErr , "unable to update status after state update" )
304322 return hr , updateStatusErr
305323 }
324+ // Record progressing status
325+ r .recordReadiness (hr , false )
306326 }
307327
308328 // Check status of any previous release attempt.
@@ -666,6 +686,29 @@ func (r *HelmReleaseReconciler) event(hr v2.HelmRelease, revision, severity, msg
666686 }
667687}
668688
689+ func (r * HelmReleaseReconciler ) recordReadiness (hr v2.HelmRelease , deleted bool ) {
690+ if r .MetricsRecorder == nil {
691+ return
692+ }
693+
694+ objRef , err := reference .GetReference (r .Scheme , & hr )
695+ if err != nil {
696+ r .Log .WithValues (
697+ strings .ToLower (hr .Kind ),
698+ fmt .Sprintf ("%s/%s" , hr .GetNamespace (), hr .GetName ()),
699+ ).Error (err , "unable to record readiness metric" )
700+ return
701+ }
702+ if rc := meta .GetCondition (hr .Status .Conditions , meta .ReadyCondition ); rc != nil {
703+ r .MetricsRecorder .RecordCondition (* objRef , * rc , deleted )
704+ } else {
705+ r .MetricsRecorder .RecordCondition (* objRef , meta.Condition {
706+ Type : meta .ReadyCondition ,
707+ Status : corev1 .ConditionUnknown ,
708+ }, deleted )
709+ }
710+ }
711+
669712func helmChartFromTemplate (hr v2.HelmRelease ) * sourcev1.HelmChart {
670713 template := hr .Spec .Chart
671714 return & sourcev1.HelmChart {
0 commit comments