diff --git a/internal/controllers/watchdog/controller.go b/internal/controllers/watchdog/controller.go index 5fae6dd3..f698a15d 100644 --- a/internal/controllers/watchdog/controller.go +++ b/internal/controllers/watchdog/controller.go @@ -35,11 +35,21 @@ func (c *watchdogController) Reconcile(ctx context.Context, req ctrl.Request) (c return ctrl.Result{}, err } + var inputsMissing int + var notInLockstep int + var withoutSynthesizers int var pendingInit int var pending int var unready int var terminal int for _, comp := range list.Items { + if c.hasNoSynthesizer(&comp, ctx) { + withoutSynthesizers++ + } + + if c.waitingOnInputs(&comp, ctx) { + inputsMissing++ + } if c.pendingInitialReconciliation(&comp) { pendingInit++ } @@ -54,6 +64,9 @@ func (c *watchdogController) Reconcile(ctx context.Context, req ctrl.Request) (c } } + waitingOnInputs.Set(float64(inputsMissing)) + inputsNotInLockstep.Set(float64(notInLockstep)) + compositionsWithoutSynthesizers.Set(float64(withoutSynthesizers)) pendingInitialReconciliation.Set(float64(pendingInit)) stuckReconciling.Set(float64(pending)) pendingReadiness.Set(float64(unready)) @@ -62,6 +75,32 @@ func (c *watchdogController) Reconcile(ctx context.Context, req ctrl.Request) (c return ctrl.Result{}, nil } +func (c *watchdogController) getSynthesizer(comp *apiv1.Composition, ctx context.Context) (*apiv1.Synthesizer, error) { + syn := &apiv1.Synthesizer{} + syn.Name = comp.Spec.Synthesizer.Name + err := c.client.Get(ctx, client.ObjectKeyFromObject(syn), syn) + return syn, err +} + +func (c *watchdogController) hasNoSynthesizer(comp *apiv1.Composition, ctx context.Context) bool { + _, err := c.getSynthesizer(comp, ctx) + return err != nil +} + +func (c *watchdogController) getInputsExist(comp *apiv1.Composition, ctx context.Context) bool { + syn, err := c.getSynthesizer(comp, ctx) + return (err != nil) || comp.InputsExist(syn) +} + +func (c *watchdogController) getNotInLockstep(comp *apiv1.Composition, ctx context.Context) bool { + syn, err := c.getSynthesizer(comp, ctx) + return (err != nil) || comp.InputsOutOfLockstep(syn) +} + +func (c *watchdogController) waitingOnInputs(comp *apiv1.Composition, ctx context.Context) bool { + return !c.getInputsExist(comp, ctx) && time.Since(comp.CreationTimestamp.Time) > c.threshold +} + func (c *watchdogController) pendingInitialReconciliation(comp *apiv1.Composition) bool { return !synthesisHasReconciled(comp.Status.CurrentSynthesis) && !synthesisHasReconciled(comp.Status.PreviousSynthesis) && diff --git a/internal/controllers/watchdog/metrics.go b/internal/controllers/watchdog/metrics.go index 13b8ab9d..d7aa5570 100644 --- a/internal/controllers/watchdog/metrics.go +++ b/internal/controllers/watchdog/metrics.go @@ -6,6 +6,30 @@ import ( ) var ( + waitingOnInputs = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: "eno_compositions_inputs_missing_total", + Help: "Number of compositions that are missing input resources", + }, + ) + +<<<<<<< HEAD +======= + inputsNotInLockstep = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: "eno_compositions_inputs_not_in_lockstep_total", + Help: "Number of compositions that have input resources that are not in lockstep with the composition's current state", + }, + ) + + compositionsWithoutSynthesizers = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: "eno_compositions_without_synthesizers_total", + Help: "Number of compositions that do not have synthesizers", + }, + ) + +>>>>>>> 58de1c7 (add metrics for inputs not in lock-step and for comps without synthesizers) pendingInitialReconciliation = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "eno_compositions_pending_initial_reconciliation", @@ -36,5 +60,5 @@ var ( ) func init() { - metrics.Registry.MustRegister(pendingInitialReconciliation, stuckReconciling, pendingReadiness, terminalErrors) + metrics.Registry.MustRegister(waitingOnInputs, pendingInitialReconciliation, stuckReconciling, pendingReadiness, terminalErrors) }