From 9412c0529ad10682b15a48f2068f8518ce708de9 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Mon, 16 Jun 2025 17:01:13 -0400 Subject: [PATCH] feat: add monitoring system and alerting - Implemented a basic monitoring system with alerting capabilities. - Introduced `MonitoringAlertingScore` and related traits (`MonitoringSystem`, `ScrapeTarget`, `AlertRule`). - Added `MonitoringAlertingInterpret` to handle the execution of monitoring configurations. - Defined interfaces for Prometheus integration (PrometheusReceiver, PrometheusRule, PrometheusScrapeTarget). - Introduced `CloneBox` trait to enable cloning boxed trait objects. - Refactored Prometheus related traits to require `Debug` implementation. - Implemented basic placeholder logic for Prometheus configuration and alerting. - Updated existing traits to include `Send` and `Sync` where appropriate. --- Cargo.lock | 9 +++ examples/lamp/src/main.rs | 4 +- .../alert_channel/discord_alert_channel.rs | 65 +++++-------------- .../src/modules/monitoring/alert_receiver.rs | 14 ++-- harmony/src/modules/monitoring/alert_rule.rs | 2 +- .../modules/monitoring/monitoring_alerting.rs | 57 +++++++++------- harmony/src/modules/monitoring/prometheus.rs | 18 +++-- .../src/modules/monitoring/scrape_target.rs | 2 +- 8 files changed, 82 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2d8c40..426f5f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2387,6 +2387,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "monitoring" +version = "0.1.0" +dependencies = [ + "harmony", + "harmony_cli", + "tokio", +] + [[package]] name = "native-tls" version = "0.2.14" diff --git a/examples/lamp/src/main.rs b/examples/lamp/src/main.rs index eaeb0f5..ea6476d 100644 --- a/examples/lamp/src/main.rs +++ b/examples/lamp/src/main.rs @@ -2,7 +2,7 @@ use harmony::{ data::Version, inventory::Inventory, maestro::Maestro, - modules::lamp::{LAMPConfig, LAMPScore}, + modules::{lamp::{LAMPConfig, LAMPScore}, monitoring::monitoring_alerting::MonitoringAlertingScore}, topology::{K8sAnywhereTopology, Url}, }; @@ -29,6 +29,8 @@ async fn main() { }, }; + let monitoring = MonitoringAlertingScore { alert_channel_configs: todo!() }; + // You can choose the type of Topology you want, we suggest starting with the // K8sAnywhereTopology as it is the most automatic one that enables you to easily deploy // locally, to development environment from a CI, to staging, and to production with settings diff --git a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs index e8bca1d..918cc7a 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -1,31 +1,33 @@ -//#[derive(Debug, Clone)] -//pub struct DiscordWebhookAlertChannel { -// pub webhook_url: Url, -// pub name: String, -// pub send_resolved_notifications: bool, -//} - use serde::Serialize; -use crate::{interpret::Interpret, modules::monitoring::{alert_receiver::{AlertReceiver, AlertReceiverInterpret}, alert_rule::AlertRule, prometheus::{Prometheus, PrometheusReceiver, PrometheusRule, PrometheusScrapeTarget}, scrape_target::ScrapeTarget}, score::Score, topology::Topology}; +use crate::{ + interpret::Interpret, + modules::monitoring::{ + alert_receiver::{AlertReceiver, AlertReceiverInterpret}, + prometheus::{Prometheus, PrometheusReceiver}, + }, + score::Score, + topology::Topology, +}; #[derive(Debug, Clone, Serialize)] struct DiscordWebhook; -impl DiscordWebhook { - fn as_prometheus_receiver(&self) -> PrometheusReceiver { - PrometheusReceiver {} - } -} - impl AlertReceiver for DiscordWebhook { type Sender = Prometheus; fn install(&self, sender: &Self::Sender) -> Result<(), String> { - sender.configure_receiver(self.as_prometheus_receiver()) + sender.configure_receiver(Box::new(self)) } } +impl PrometheusReceiver for DiscordWebhook { + fn get_prometheus_config( + &self, + ) -> crate::modules::monitoring::prometheus::PrometheusReceiverConfig { + todo!() + } +} #[derive(Debug, Clone, Serialize)] pub struct DiscordWebhookScore { @@ -36,41 +38,10 @@ impl Score for DiscordWebhookScore { fn create_interpret(&self) -> Box> { Box::new(AlertReceiverInterpret { receiver: Box::new(self.config.clone()), - }) + }) } fn name(&self) -> String { todo!() } } - -impl ScrapeTarget for DiscordWebhook { - type Sender = Prometheus; - - fn install(&self, sender: &Self::Sender) { - sender.configure_scrape_target(self.as_prometheus_scrape_target()) - } -} - - -impl DiscordWebhook { - fn as_prometheus_scrape_target(&self) -> PrometheusScrapeTarget { - PrometheusScrapeTarget { definition: todo!() } - } -} - - -impl AlertRule for DiscordWebhook { - type Sender = Prometheus; - - fn install(&self, sender: &Self::Sender) { - sender.configure_rule(self.as_prometheus_rule()) - } -} - - -impl DiscordWebhook { - fn as_prometheus_rule(&self) -> PrometheusRule { - PrometheusRule { definition: todo!() } - } -} diff --git a/harmony/src/modules/monitoring/alert_receiver.rs b/harmony/src/modules/monitoring/alert_receiver.rs index c8a7028..f154373 100644 --- a/harmony/src/modules/monitoring/alert_receiver.rs +++ b/harmony/src/modules/monitoring/alert_receiver.rs @@ -9,9 +9,9 @@ use crate::{ topology::Topology, }; -use super::prometheus::AlertSender; +use super::{monitoring_alerting::CloneBox, prometheus::AlertSender}; -pub trait AlertReceiver: Debug + Send + Sync { +pub trait AlertReceiver: Debug + Send + Sync + CloneBox { type Sender: AlertSender; fn install(&self, sender: &Self::Sender) -> Result<(), String>; @@ -23,16 +23,16 @@ struct AlertReceiverConfig { } #[derive(Debug)] -pub struct AlertReceiverInterpret { - pub receiver: Box>, +pub struct AlertReceiverInterpret { + pub receiver: Box>, } #[async_trait] -impl Interpret for AlertReceiverInterpret { +impl Interpret for AlertReceiverInterpret { async fn execute( &self, - inventory: &Inventory, - topology: &T, + _inventory: &Inventory, + _topology: &T, ) -> Result { todo!() } diff --git a/harmony/src/modules/monitoring/alert_rule.rs b/harmony/src/modules/monitoring/alert_rule.rs index c64014c..d4f197c 100644 --- a/harmony/src/modules/monitoring/alert_rule.rs +++ b/harmony/src/modules/monitoring/alert_rule.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use super::prometheus::AlertSender; -pub trait AlertRule: Debug { +pub trait AlertRule: Debug + Send + Sync { type Sender: AlertSender; fn install(&self, sender: &Self::Sender); diff --git a/harmony/src/modules/monitoring/monitoring_alerting.rs b/harmony/src/modules/monitoring/monitoring_alerting.rs index d170a93..f815ae0 100644 --- a/harmony/src/modules/monitoring/monitoring_alerting.rs +++ b/harmony/src/modules/monitoring/monitoring_alerting.rs @@ -1,35 +1,41 @@ +use std::sync::Arc; + use async_trait::async_trait; use serde::Serialize; -use serde_value::Value; -use crate::topology::oberservability::monitoring::{AlertChannelConfig, Monitor}; use crate::{ data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::Inventory, score::Score, - topology::{HelmCommand, Topology}, + topology::Topology, }; use super::alert_receiver::AlertReceiver; use super::alert_rule::AlertRule; use super::scrape_target::ScrapeTarget; +pub trait MonitoringSystem: std::fmt::Debug + Clone + Serialize + 'static {} -pub trait MonitoringSystem {} - - -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone)] pub struct MonitoringAlertingScore { - alert_receivers: Vec>>, - alert_rules: Vec>>, - scrape_targets: Vec>>, + alert_receivers: Arc>>>, + alert_rules: Arc>>>, + scrape_targets: Arc>>>, } -impl Score for MonitoringAlertingScore { +impl Serialize for MonitoringAlertingScore { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer { + todo!() + } +} + +impl Score for MonitoringAlertingScore { fn create_interpret(&self) -> Box> { Box::new(MonitoringAlertingInterpret { - score: self.clone(), + score: Arc::new(self.clone()), }) } @@ -39,24 +45,18 @@ impl Score for MonitoringAlertingScore { } #[derive(Debug)] -struct MonitoringAlertingInterpret { - score: MonitoringAlertingScore, +struct MonitoringAlertingInterpret { + score: Arc>, } #[async_trait] -impl Interpret for MonitoringAlertingInterpret { +impl Interpret for MonitoringAlertingInterpret { async fn execute( &self, inventory: &Inventory, topology: &T, ) -> Result { - topology - .provision_monitor( - inventory, - topology, - self.score.alert_channel_configs.clone(), - ) - .await + todo!() } fn get_name(&self) -> InterpretName { @@ -75,3 +75,16 @@ impl Interpret for MonitoringAlertingInterpret { todo!() } } + +pub trait CloneBox { + fn clone_box(&self) -> Box; +} + +impl CloneBox for C +where + C: Clone + 'static, +{ + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} diff --git a/harmony/src/modules/monitoring/prometheus.rs b/harmony/src/modules/monitoring/prometheus.rs index 270fd84..e1ab33a 100644 --- a/harmony/src/modules/monitoring/prometheus.rs +++ b/harmony/src/modules/monitoring/prometheus.rs @@ -6,24 +6,23 @@ use crate::{ data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::Inventory, - score::Score, topology::Topology, }; use std::fmt::Debug; -pub trait AlertSender {} +pub trait AlertSender: std::fmt::Debug {} #[derive(Debug, Clone, Serialize)] pub struct Prometheus {} impl Prometheus { - pub fn configure_receiver(&self, receiver: PrometheusReceiver) -> Result<(), String> { + pub fn configure_receiver(&self, _receiver: Box<&dyn PrometheusReceiver>) -> Result<(), String> { todo!() } - pub fn configure_rule(&self, rule: PrometheusRule) { + pub fn configure_rule(&self, _rule: Box<&dyn PrometheusRule>) { todo!() } - pub fn configure_scrape_target(&self, target: PrometheusScrapeTarget) { + pub fn configure_scrape_target(&self, _target: Box<&dyn PrometheusScrapeTarget>) { todo!() } } @@ -36,7 +35,7 @@ pub trait PrometheusCapability { impl AlertSender for Prometheus {} -pub trait PrometheusReceiver{ +pub trait PrometheusReceiver { fn get_prometheus_config(&self) -> PrometheusReceiverConfig; } @@ -45,7 +44,7 @@ pub struct PrometheusReceiverConfig { // config } -pub trait PrometheusRule{ +pub trait PrometheusRule { fn get_prometheus_config(&self) -> PrometheusRuleConfig; } @@ -74,8 +73,8 @@ pub struct PrometheusMonitoringInterpret {} impl Interpret for PrometheusMonitoringInterpret { async fn execute( &self, - inventory: &Inventory, - topology: &T, + _inventory: &Inventory, + _topology: &T, ) -> Result { todo!() } @@ -96,4 +95,3 @@ impl Interpret for PrometheusMonitoringIn todo!() } } - diff --git a/harmony/src/modules/monitoring/scrape_target.rs b/harmony/src/modules/monitoring/scrape_target.rs index 954bf0c..9ce73c7 100644 --- a/harmony/src/modules/monitoring/scrape_target.rs +++ b/harmony/src/modules/monitoring/scrape_target.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use super::prometheus::AlertSender; -pub trait ScrapeTarget: Debug { +pub trait ScrapeTarget: Debug + Send + Sync { type Sender: AlertSender; fn install(&self, sender: &Self::Sender);