@@ -100,12 +100,17 @@ func (r *MemgraphClusterReconciler) Reconcile(ctx context.Context, req ctrl.Requ
100100 // Initialize status if needed
101101 if cluster .Status .Phase == "" {
102102 cluster .Status .Phase = memgraphv1alpha1 .ClusterPhasePending
103+ r .Recorder .Event (cluster , corev1 .EventTypeNormal , EventReasonClusterCreated ,
104+ "Cluster created, starting initialization" )
103105 if err := r .Status ().Update (ctx , cluster ); err != nil {
104106 return ctrl.Result {}, err
105107 }
106108 return ctrl.Result {Requeue : true }, nil
107109 }
108110
111+ // Track previous phase for event emission
112+ previousPhase := cluster .Status .Phase
113+
109114 // Reconcile resources
110115 result , err := r .reconcileResources (ctx , cluster , log )
111116
@@ -114,7 +119,7 @@ func (r *MemgraphClusterReconciler) Reconcile(ctx context.Context, req ctrl.Requ
114119 r .metrics .RecordReconcileDuration (cluster .Name , cluster .Namespace , duration )
115120
116121 if err != nil {
117- r .Recorder .Event (cluster , corev1 .EventTypeWarning , "ReconcileError" , err .Error ())
122+ r .Recorder .Event (cluster , corev1 .EventTypeWarning , EventReasonReconcileError , err .Error ())
118123 r .metrics .RecordReconcileOperation (cluster .Name , cluster .Namespace , "error" )
119124 return result , err
120125 }
@@ -123,6 +128,9 @@ func (r *MemgraphClusterReconciler) Reconcile(ctx context.Context, req ctrl.Requ
123128 r .metrics .RecordReconcileOperation (cluster .Name , cluster .Namespace , "success" )
124129 r .metrics .RecordClusterPhase (cluster .Name , cluster .Namespace , string (cluster .Status .Phase ))
125130
131+ // Emit phase transition events
132+ r .emitPhaseTransitionEvents (cluster , previousPhase )
133+
126134 replicas := cluster .Spec .Replicas
127135 if replicas == 0 {
128136 replicas = 3
@@ -210,7 +218,7 @@ func (r *MemgraphClusterReconciler) reconcileResources(ctx context.Context, clus
210218 } else {
211219 if err := r .replicationManager .ConfigureReplication (ctx , cluster , pods , writeInstance , log ); err != nil {
212220 log .Error ("failed to configure replication" , zap .Error (err ))
213- r .Recorder .Event (cluster , corev1 .EventTypeWarning , "ReplicationError" ,
221+ r .Recorder .Event (cluster , corev1 .EventTypeWarning , EventReasonReplicationError ,
214222 fmt .Sprintf ("Failed to configure replication: %v" , err ))
215223 } else {
216224 health , err := r .replicationManager .CheckReplicationHealth (ctx , cluster , writeInstance , log )
@@ -240,7 +248,10 @@ func (r *MemgraphClusterReconciler) reconcileResources(ctx context.Context, clus
240248 }
241249 }
242250
243- // 11. Update status
251+ // 11. Collect storage metrics from all running pods
252+ r .collectStorageMetrics (ctx , cluster , pods , writeInstance , log )
253+
254+ // 12. Update status
244255 if err := r .updateStatus (ctx , cluster , pods , writeInstance , registeredReplicas ); err != nil {
245256 return ctrl.Result {}, err
246257 }
@@ -272,7 +283,7 @@ func (r *MemgraphClusterReconciler) ensureReplicationManager() error {
272283 return fmt .Errorf ("failed to create memgraph client: %w" , err )
273284 }
274285
275- r .replicationManager = NewReplicationManager (mgClient )
286+ r .replicationManager = NewReplicationManager (mgClient , r . Recorder )
276287 return nil
277288}
278289
@@ -311,7 +322,7 @@ func (r *MemgraphClusterReconciler) reconcileStatefulSet(ctx context.Context, cl
311322 log .Info ("creating StatefulSet" ,
312323 zap .String ("statefulset" , desired .Name ),
313324 zap .Int32 ("replicas" , * desired .Spec .Replicas ))
314- r .Recorder .Event (cluster , corev1 .EventTypeNormal , "CreatingStatefulSet" ,
325+ r .Recorder .Event (cluster , corev1 .EventTypeNormal , EventReasonCreatingStatefulSet ,
315326 fmt .Sprintf ("Creating StatefulSet %s with %d replicas" , desired .Name , * desired .Spec .Replicas ))
316327 return r .Create (ctx , desired )
317328 }
@@ -325,7 +336,7 @@ func (r *MemgraphClusterReconciler) reconcileStatefulSet(ctx context.Context, cl
325336 zap .Int32 ("currentReplicas" , * existing .Spec .Replicas ),
326337 zap .Int32 ("desiredReplicas" , * desired .Spec .Replicas ))
327338 existing .Spec .Replicas = desired .Spec .Replicas
328- r .Recorder .Event (cluster , corev1 .EventTypeNormal , "ScalingStatefulSet" ,
339+ r .Recorder .Event (cluster , corev1 .EventTypeNormal , EventReasonScalingStatefulSet ,
329340 fmt .Sprintf ("Scaling StatefulSet %s to %d replicas" , existing .Name , * desired .Spec .Replicas ))
330341 return r .Update (ctx , existing )
331342 }
@@ -360,7 +371,7 @@ func (r *MemgraphClusterReconciler) reconcileWriteService(ctx context.Context, c
360371 zap .String ("previousInstance" , currentWriteInstance ),
361372 zap .String ("newInstance" , writeInstance ))
362373 existing .Spec .Selector = desired .Spec .Selector
363- r .Recorder .Event (cluster , corev1 .EventTypeNormal , "UpdatedWriteService" ,
374+ r .Recorder .Event (cluster , corev1 .EventTypeNormal , EventReasonUpdatedWriteService ,
364375 fmt .Sprintf ("Write service now pointing to %s" , writeInstance ))
365376 return r .Update (ctx , existing )
366377 }
@@ -558,6 +569,62 @@ func conditionMessage(ok bool, trueMsg, falseMsg string) string {
558569 return falseMsg
559570}
560571
572+ // collectStorageMetrics collects storage metrics from all running pods
573+ func (r * MemgraphClusterReconciler ) collectStorageMetrics (
574+ ctx context.Context ,
575+ cluster * memgraphv1alpha1.MemgraphCluster ,
576+ pods []corev1.Pod ,
577+ writeInstance string ,
578+ log * zap.Logger ,
579+ ) {
580+ if r .replicationManager == nil || r .replicationManager .Client () == nil {
581+ return
582+ }
583+
584+ mgClient := r .replicationManager .Client ()
585+ for _ , pod := range pods {
586+ if ! isPodReady (& pod ) {
587+ continue
588+ }
589+
590+ role := "replica"
591+ if pod .Name == writeInstance {
592+ role = "main"
593+ }
594+
595+ info , err := mgClient .GetStorageInfo (ctx , cluster .Namespace , pod .Name )
596+ if err != nil {
597+ log .Debug ("failed to collect storage metrics" ,
598+ zap .String ("pod" , pod .Name ),
599+ zap .Error (err ))
600+ continue
601+ }
602+
603+ r .metrics .RecordStorageInfo (cluster .Name , cluster .Namespace , pod .Name , role , info )
604+ }
605+ }
606+
607+ // emitPhaseTransitionEvents emits events when cluster phase changes
608+ func (r * MemgraphClusterReconciler ) emitPhaseTransitionEvents (
609+ cluster * memgraphv1alpha1.MemgraphCluster ,
610+ previousPhase memgraphv1alpha1.ClusterPhase ,
611+ ) {
612+ currentPhase := cluster .Status .Phase
613+ if currentPhase == previousPhase {
614+ return
615+ }
616+
617+ switch {
618+ case currentPhase == memgraphv1alpha1 .ClusterPhaseRunning :
619+ r .Recorder .Event (cluster , corev1 .EventTypeNormal , EventReasonClusterReady ,
620+ fmt .Sprintf ("Cluster is ready with %d instances" , cluster .Status .ReadyInstances ))
621+ case previousPhase == memgraphv1alpha1 .ClusterPhaseRunning &&
622+ currentPhase == memgraphv1alpha1 .ClusterPhaseInitializing :
623+ r .Recorder .Event (cluster , corev1 .EventTypeWarning , EventReasonClusterDegraded ,
624+ fmt .Sprintf ("Cluster degraded: %d instances ready" , cluster .Status .ReadyInstances ))
625+ }
626+ }
627+
561628// SetupWithManager sets up the controller with the Manager.
562629func (r * MemgraphClusterReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
563630 return ctrl .NewControllerManagedBy (mgr ).
0 commit comments