diff --git a/src/alerts/alert_structs.rs b/src/alerts/alert_structs.rs index a37927626..59b45bddd 100644 --- a/src/alerts/alert_structs.rs +++ b/src/alerts/alert_structs.rs @@ -757,6 +757,10 @@ pub struct StateTransition { pub state: AlertState, /// Timestamp when this state was set/updated pub last_updated_at: DateTime, + /// The previous alert state before this transition, if any + pub previous_alert_state: Option, + /// Duration in seconds + pub previous_state_duration: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -768,10 +772,20 @@ pub struct AlertStateEntry { impl StateTransition { /// Creates a new state transition with the current timestamp - pub fn new(state: AlertState) -> Self { + pub fn new( + state: AlertState, + previous_alert_state: Option, + previous_alert_time: Option>, + ) -> Self { + let now = Utc::now(); + // calculate duration if previous alert time is provided + let previous_state_duration = + previous_alert_time.map(|alert_time| (now - alert_time).num_seconds()); Self { state, - last_updated_at: Utc::now(), + last_updated_at: now, + previous_alert_state, + previous_state_duration, } } } @@ -781,7 +795,7 @@ impl AlertStateEntry { pub fn new(alert_id: Ulid, initial_state: AlertState) -> Self { Self { alert_id, - states: vec![StateTransition::new(initial_state)], + states: vec![StateTransition::new(initial_state, None, None)], } } @@ -792,7 +806,11 @@ impl AlertStateEntry { Some(last_transition) => { if last_transition.state != new_state { // State changed - add new transition - self.states.push(StateTransition::new(new_state)); + self.states.push(StateTransition::new( + new_state, + Some(last_transition.state), + Some(last_transition.last_updated_at), + )); true } else { // If state hasn't changed, do nothing - preserve the original timestamp @@ -801,7 +819,8 @@ impl AlertStateEntry { } None => { // No previous states - add the first one - self.states.push(StateTransition::new(new_state)); + self.states + .push(StateTransition::new(new_state, None, None)); true } } diff --git a/src/handlers/http/alerts.rs b/src/handlers/http/alerts.rs index a5e5c1938..e8bfd59e3 100644 --- a/src/handlers/http/alerts.rs +++ b/src/handlers/http/alerts.rs @@ -44,15 +44,19 @@ const MAX_LIMIT: usize = 1000; const DEFAULT_LIMIT: usize = 100; /// Query parameters for listing alerts -struct ListQueryParams { - tags_list: Vec, - offset: usize, - limit: usize, - other_fields_filters: HashMap, +pub struct ListQueryParams { + /// Comma-separated tag filters; empty if no tag filtering + pub tags_list: Vec, + /// Number of results to skip (default: 0) + pub offset: usize, + /// Maximum results to return (1-1000, default: 100) + pub limit: usize, + /// Additional field filters not covered by reserved params + pub other_fields_filters: HashMap, } /// Parse and validate query parameters for listing alerts -fn parse_list_query_params( +pub fn parse_list_query_params( query_map: &HashMap, ) -> Result { let mut tags_list = Vec::new();