@@ -7,11 +7,16 @@ use actions::{Action, ActionExecutor, ExecuteAction, LogAction, LogLevel, PowerS
77use bus:: create_event_bus;
88use engine_core:: event:: EventKind ;
99use engine_core:: plugin:: EventSourcePlugin ;
10+ use metrics:: {
11+ record_action_execution, record_config_reload, record_event,
12+ record_event_processing_duration, record_rule_match, record_rule_match_duration,
13+ record_rule_evaluation, MetricsCollector ,
14+ } ;
1015use rules:: { EventKindMatcher , FilePatternMatcher , Rule , RuleMatcher , WindowMatcher , WindowEventType } ;
1116use std:: path:: PathBuf ;
1217use std:: sync:: Arc ;
1318use tokio:: sync:: mpsc;
14- use tokio:: time:: { Duration , timeout} ;
19+ use tokio:: time:: { Duration , timeout, Instant } ;
1520use tracing:: { error, info, warn} ;
1621
1722pub struct Engine {
@@ -23,10 +28,13 @@ pub struct Engine {
2328 event_sender : Option < mpsc:: Sender < engine_core:: event:: Event > > ,
2429 shutdown_flag : Arc < std:: sync:: atomic:: AtomicBool > ,
2530 config_reload_rx : Option < mpsc:: Receiver < ( ) > > ,
31+ metrics : Arc < MetricsCollector > ,
2632}
2733
2834impl Engine {
2935 pub fn new ( config : Config , config_path : Option < PathBuf > ) -> Self {
36+ let metrics = Arc :: new ( MetricsCollector :: new ( ) ) ;
37+
3038 Self {
3139 config,
3240 config_path,
@@ -36,8 +44,14 @@ impl Engine {
3644 event_sender : None ,
3745 shutdown_flag : Arc :: new ( std:: sync:: atomic:: AtomicBool :: new ( false ) ) ,
3846 config_reload_rx : None ,
47+ metrics,
3948 }
4049 }
50+
51+ /// Get a reference to the metrics collector
52+ pub fn metrics ( & self ) -> Arc < MetricsCollector > {
53+ self . metrics . clone ( )
54+ }
4155
4256 pub fn take_config_reload_rx ( & mut self ) -> Option < mpsc:: Receiver < ( ) > > {
4357 self . config_reload_rx . take ( )
@@ -62,28 +76,66 @@ impl Engine {
6276 // Start event processing loop
6377 let rules = self . rules . clone ( ) ;
6478 let action_executor = self . action_executor . clone ( ) ;
79+ let metrics = self . metrics . clone ( ) ;
6580
6681 tokio:: spawn ( async move {
6782 info ! ( "Event processing loop started" ) ;
6883
6984 while let Some ( event) = receiver. recv ( ) . await {
85+ let start_time = Instant :: now ( ) ;
86+ let event_source = event. source . clone ( ) ;
87+ let event_type = format ! ( "{:?}" , event. kind) ;
88+
89+ // Record event received
90+ record_event ( & metrics, & event_source, & event_type) ;
91+
7092 tracing:: debug!( "Processing event: {:?} from {}" , event. kind, event. source) ;
7193
7294 for ( idx, rule) in rules. iter ( ) . enumerate ( ) {
7395 if !rule. enabled {
7496 continue ;
7597 }
7698
77- if rule. matches ( & event) {
99+ // Record rule evaluation
100+ record_rule_evaluation ( & metrics, & rule. name ) ;
101+
102+ let match_start = Instant :: now ( ) ;
103+ let matched = rule. matches ( & event) ;
104+ record_rule_match_duration ( & metrics, & rule. name , match_start. elapsed ( ) ) ;
105+
106+ if matched {
107+ // Record successful rule match
108+ record_rule_match ( & metrics, & rule. name ) ;
78109 info ! ( "Rule '{}' matched event from {}" , rule. name, event. source) ;
79110
80111 let action_name = format ! ( "rule_{}_action" , idx) ;
112+ let action_start = Instant :: now ( ) ;
113+
81114 match action_executor. execute ( & action_name, & event) {
82- Ok ( result) => info ! ( "Action executed successfully: {:?}" , result) ,
83- Err ( e) => error ! ( "Action execution failed: {}" , e) ,
115+ Ok ( result) => {
116+ record_action_execution (
117+ & metrics,
118+ & action_name,
119+ true ,
120+ action_start. elapsed ( )
121+ ) ;
122+ info ! ( "Action executed successfully: {:?}" , result) ;
123+ }
124+ Err ( e) => {
125+ record_action_execution (
126+ & metrics,
127+ & action_name,
128+ false ,
129+ action_start. elapsed ( )
130+ ) ;
131+ error ! ( "Action execution failed: {}" , e) ;
132+ }
84133 }
85134 }
86135 }
136+
137+ // Record total event processing duration
138+ record_event_processing_duration ( & metrics, start_time. elapsed ( ) ) ;
87139 }
88140
89141 info ! ( "Event processing loop stopped" ) ;
@@ -485,6 +537,7 @@ public class MediaKeys {
485537 "New configuration validation failed: {}, keeping current config" ,
486538 e
487539 ) ;
540+ record_config_reload ( & self . metrics , false ) ;
488541 return Err ( EngineError :: Config ( e. to_string ( ) ) ) ;
489542 }
490543
@@ -509,30 +562,66 @@ public class MediaKeys {
509562 if let Some ( _sender) = & self . event_sender {
510563 let rules = self . rules . clone ( ) ;
511564 let action_executor = self . action_executor . clone ( ) ;
565+ let metrics = self . metrics . clone ( ) ;
512566 let mut receiver = bus:: create_event_bus ( self . config . engine . event_buffer_size ) . 1 ;
513567
514568 tokio:: spawn ( async move {
515569 while let Some ( event) = receiver. recv ( ) . await {
570+ let start_time = Instant :: now ( ) ;
571+ let event_source = event. source . clone ( ) ;
572+ let event_type = format ! ( "{:?}" , event. kind) ;
573+
574+ record_event ( & metrics, & event_source, & event_type) ;
575+
516576 tracing:: debug!( "Processing event: {:?} from {}" , event. kind, event. source) ;
517577
518578 for ( idx, rule) in rules. iter ( ) . enumerate ( ) {
519579 if !rule. enabled {
520580 continue ;
521581 }
522582
523- if rule. matches ( & event) {
583+ record_rule_evaluation ( & metrics, & rule. name ) ;
584+
585+ let match_start = Instant :: now ( ) ;
586+ let matched = rule. matches ( & event) ;
587+ record_rule_match_duration ( & metrics, & rule. name , match_start. elapsed ( ) ) ;
588+
589+ if matched {
590+ record_rule_match ( & metrics, & rule. name ) ;
524591 info ! ( "Rule '{}' matched event from {}" , rule. name, event. source) ;
525592
526593 let action_name = format ! ( "rule_{}_action" , idx) ;
594+ let action_start = Instant :: now ( ) ;
595+
527596 match action_executor. execute ( & action_name, & event) {
528- Ok ( result) => info ! ( "Action executed successfully: {:?}" , result) ,
529- Err ( e) => error ! ( "Action execution failed: {}" , e) ,
597+ Ok ( result) => {
598+ record_action_execution (
599+ & metrics,
600+ & action_name,
601+ true ,
602+ action_start. elapsed ( )
603+ ) ;
604+ info ! ( "Action executed successfully: {:?}" , result) ;
605+ }
606+ Err ( e) => {
607+ record_action_execution (
608+ & metrics,
609+ & action_name,
610+ false ,
611+ action_start. elapsed ( )
612+ ) ;
613+ error ! ( "Action execution failed: {}" , e) ;
614+ }
530615 }
531616 }
532617 }
618+
619+ record_event_processing_duration ( & metrics, start_time. elapsed ( ) ) ;
533620 }
534621 } ) ;
535622 }
623+
624+ record_config_reload ( & self . metrics , true ) ;
536625
537626 let status = self . get_status ( ) ;
538627 info ! (
0 commit comments