From 527b88ce3b4fc561936e7b7769dfe3f82ee425f2 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Wed, 18 Jun 2025 13:09:11 -0400 Subject: [PATCH] wip : new architecture test for Alerting, this one binds everything at the Score level. The score itself knows exactly what kind of sender is deployed on what such as Prometheus Sender deployed on Kubernetes. This still allows for extensibility where users can create new scores for new combinations easily, and allows for a generic AlertInterpret that handles reusable core logic to manage alerting concerns within Harmony --- Cargo.lock | 18 ++-- examples/monitoring/Cargo.toml | 2 +- examples/monitoring/src/main.rs | 7 +- harmony/src/domain/topology/k8s_anywhere.rs | 5 -- harmony/src/modules/monitoring/alert_score.rs | 86 +++++++++++++++++++ .../kube_prometheus_helm_chart_score.rs | 3 +- harmony/src/modules/monitoring/mod.rs | 1 + .../modules/monitoring/monitoring_alerting.rs | 28 +++--- harmony/src/modules/monitoring/prometheus.rs | 6 +- 9 files changed, 119 insertions(+), 37 deletions(-) create mode 100644 harmony/src/modules/monitoring/alert_score.rs diff --git a/Cargo.lock b/Cargo.lock index 426f5f9..a9c8654 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1040,6 +1040,15 @@ dependencies = [ "url", ] +[[package]] +name = "example-monitoring" +version = "0.1.0" +dependencies = [ + "harmony", + "harmony_cli", + "tokio", +] + [[package]] name = "example-nanodc" version = "0.1.0" @@ -2387,15 +2396,6 @@ 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/monitoring/Cargo.toml b/examples/monitoring/Cargo.toml index 57f291c..af42491 100644 --- a/examples/monitoring/Cargo.toml +++ b/examples/monitoring/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "monitoring" +name = "example-monitoring" edition = "2024" version.workspace = true readme.workspace = true diff --git a/examples/monitoring/src/main.rs b/examples/monitoring/src/main.rs index 18ba474..3890c11 100644 --- a/examples/monitoring/src/main.rs +++ b/examples/monitoring/src/main.rs @@ -1,11 +1,11 @@ use harmony::{ inventory::Inventory, maestro::Maestro, - modules::monitoring::monitoring_alerting::{MonitoringAlertingScore, MonitoringSystem}, - topology::K8sAnywhereTopology, + modules::monitoring::alert_score::PrometheusAlertingScore, topology::K8sAnywhereTopology, }; #[tokio::main] async fn main() { + let alerting_score = PrometheusAlertingScore { receivers: vec![] }; let mut maestro = Maestro::::initialize( Inventory::autoload(), K8sAnywhereTopology::from_env(), @@ -14,10 +14,11 @@ async fn main() { .unwrap(); //let monitoring = MonitoringAlertingScore { - // alert_receivers: vec![], + // alert_receivers: vec![], // alert_rules: vec![], // scrape_targets: vec![], //}; //maestro.register_all(vec![Box::new(monitoring)]); + maestro.register_all(vec![Box::new(alerting_score)]); harmony_cli::init(maestro, None).await.unwrap(); } diff --git a/harmony/src/domain/topology/k8s_anywhere.rs b/harmony/src/domain/topology/k8s_anywhere.rs index c143805..6742b5a 100644 --- a/harmony/src/domain/topology/k8s_anywhere.rs +++ b/harmony/src/domain/topology/k8s_anywhere.rs @@ -17,11 +17,6 @@ use crate::{ use super::{ HelmCommand, K8sclient, Topology, k8s::K8sClient, - oberservability::{ - K8sMonitorConfig, - k8s::K8sMonitor, - monitoring::{AlertChannelConfig, Monitor}, - }, tenant::{TenantConfig, TenantManager, k8s::K8sTenantManager}, }; diff --git a/harmony/src/modules/monitoring/alert_score.rs b/harmony/src/modules/monitoring/alert_score.rs new file mode 100644 index 0000000..1971e55 --- /dev/null +++ b/harmony/src/modules/monitoring/alert_score.rs @@ -0,0 +1,86 @@ +use async_trait::async_trait; +use serde::Serialize; + +use crate::{ + data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::Inventory, score::Score, topology::{HelmCommand, Topology} +}; + +#[async_trait] +pub trait Installable { + async fn ensure_installed(&self) -> Result<(), InterpretError>; +} + +pub trait AlertSender: Send + Sync + std::fmt::Debug + Installable {} + +pub trait AlertReceiver: std::fmt::Debug + Send + Sync { + fn install(&self, sender: &S) -> Result<(), InterpretError>; +} + +#[derive(Clone, Debug, Serialize)] +pub struct PrometheusAlertingScore { + pub receivers: Vec>>, +} + +impl Serialize for Box> { + fn serialize(&self, _serializer: S) -> Result + where + S: serde::Serializer, + { + todo!() + } +} +impl Clone for Box> { + fn clone(&self) -> Self { + todo!() + } +} + +impl Score for PrometheusAlertingScore { + fn create_interpret(&self) -> Box> { + Box::new(AlertingInterpret { sender: Prometheus {}, receivers: todo!() }) + } + + fn name(&self) -> String { + "PrometheusAlertingScore".to_string() + } +} + +pub struct Prometheus; + +#[derive(Debug)] +pub struct AlertingInterpret { + pub sender: S, + pub receivers: Vec>>, +} + +#[async_trait] +impl Interpret for AlertingInterpret { + #[must_use] + async fn execute( + &self, + inventory: &Inventory, + topology: &T, + ) -> Result { + + self.receivers.iter().try_for_each(|r| { + r.install(&self.sender) + })?; + todo!(); + } + + fn get_name(&self) -> InterpretName { + todo!() + } + + fn get_version(&self) -> Version { + todo!() + } + + fn get_status(&self) -> InterpretStatus { + todo!() + } + + fn get_children(&self) -> Vec { + todo!() + } +} diff --git a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs index 14680d9..2377627 100644 --- a/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs +++ b/harmony/src/modules/monitoring/kube_prometheus/kube_prometheus_helm_chart_score.rs @@ -1,5 +1,4 @@ use super::config::KubePrometheusConfig; -use log::info; use non_blank_string_rs::NonBlankString; use std::str::FromStr; @@ -26,7 +25,7 @@ pub fn kube_prometheus_helm_chart_score() -> HelmChartScore { let node_exporter = config.node_exporter.to_string(); let prometheus_operator = config.prometheus_operator.to_string(); let prometheus = config.prometheus.to_string(); - let mut values = format!( + let values = format!( r#" additionalPrometheusRulesMap: pods-status-alerts: diff --git a/harmony/src/modules/monitoring/mod.rs b/harmony/src/modules/monitoring/mod.rs index 270ee39..5f5fc19 100644 --- a/harmony/src/modules/monitoring/mod.rs +++ b/harmony/src/modules/monitoring/mod.rs @@ -5,3 +5,4 @@ pub mod kube_prometheus; pub mod monitoring_alerting; pub mod prometheus; pub mod scrape_target; +pub mod alert_score; diff --git a/harmony/src/modules/monitoring/monitoring_alerting.rs b/harmony/src/modules/monitoring/monitoring_alerting.rs index cbf830e..a847a04 100644 --- a/harmony/src/modules/monitoring/monitoring_alerting.rs +++ b/harmony/src/modules/monitoring/monitoring_alerting.rs @@ -27,11 +27,6 @@ pub struct MonitoringAlertingScore { pub scrape_targets: Vec>>, } -#[derive(Clone)] -struct MonitoringConfig { - receivers: Vec>>, -} - impl Clone for Box> { fn clone(&self) -> Self { self.clone_box() @@ -49,7 +44,7 @@ impl Clone for Box> { } impl Serialize for MonitoringAlertingScore { - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, _serializer: S) -> Result where S: serde::Serializer, { @@ -84,11 +79,21 @@ impl Interpret { async fn execute( &self, - inventory: &Inventory, - topology: &T, + _inventory: &Inventory, + _topology: &T, ) -> Result { debug!("score {:#?}", self.score); - monitoring_system.install().await + todo!("Figure out a clean way to have things come together here : + We want Prometheus to be bound like this : + + DiscordWebhook (AlertReceiver) + | + Prometheus (AlertSender + Scraper + Installable) + ^ + MonitoringScore {{ alert_rules, alert_receivers, scrape_endpoints }} + (Interpret InterpretName { @@ -108,8 +113,3 @@ impl Interpret } } -impl MonitoringAlertingInterpret { - fn build_config(&self) -> MonitoringConfig { - todo!() - } -} diff --git a/harmony/src/modules/monitoring/prometheus.rs b/harmony/src/modules/monitoring/prometheus.rs index b849d5d..4849a98 100644 --- a/harmony/src/modules/monitoring/prometheus.rs +++ b/harmony/src/modules/monitoring/prometheus.rs @@ -6,18 +6,18 @@ use crate::{ data::{Id, Version}, interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, inventory::Inventory, - topology::{HelmCommand, K8sAnywhereTopology, Topology}, + topology::{K8sAnywhereTopology, Topology}, }; use std::fmt::Debug; -use super::monitoring_alerting::{MonitoringSystem, MonitoringSystemInstaller}; +use super::monitoring_alerting::MonitoringSystem; #[derive(Debug, Clone, Serialize)] pub struct Prometheus {} impl Prometheus { pub fn configure_receiver(&self, receiver: Box<&dyn PrometheusReceiver>) -> Result<(), String> { - let receiver_config = receiver.get_prometheus_config(); + let _receiver_config = receiver.get_prometheus_config(); todo!() } pub fn configure_rule(&self, _rule: Box<&dyn PrometheusRule>) {