Skip to content

Commit 1819f14

Browse files
committed
Implement Prometheus instrumentation
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
1 parent 6a04f76 commit 1819f14

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

controllers/helmrelease_controller.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

144150
func (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+
669712
func helmChartFromTemplate(hr v2.HelmRelease) *sourcev1.HelmChart {
670713
template := hr.Spec.Chart
671714
return &sourcev1.HelmChart{

main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ import (
2929
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
3030
ctrl "sigs.k8s.io/controller-runtime"
3131
"sigs.k8s.io/controller-runtime/pkg/log/zap"
32+
crtlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
3233

3334
"github.com/fluxcd/pkg/runtime/events"
35+
"github.com/fluxcd/pkg/runtime/metrics"
3436
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
3537

3638
v2 "github.com/fluxcd/helm-controller/api/v2beta1"
@@ -88,6 +90,9 @@ func main() {
8890
}
8991
}
9092

93+
metricsRecorder := metrics.NewRecorder()
94+
crtlmetrics.Registry.MustRegister(metricsRecorder.Collectors()...)
95+
9196
watchNamespace := ""
9297
if !watchAllNamespaces {
9398
watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
@@ -122,6 +127,7 @@ func main() {
122127
Scheme: mgr.GetScheme(),
123128
EventRecorder: mgr.GetEventRecorderFor("helm-controller"),
124129
ExternalEventRecorder: eventRecorder,
130+
MetricsRecorder: metricsRecorder,
125131
}).SetupWithManager(mgr, controllers.HelmReleaseReconcilerOptions{
126132
MaxConcurrentReconciles: concurrent,
127133
DependencyRequeueInterval: requeueDependency,

0 commit comments

Comments
 (0)