From f6c146b14bd01fdefc8ca26d8fa096e2faa720a5 Mon Sep 17 00:00:00 2001 From: Willem Date: Mon, 16 Jun 2025 08:45:29 -0400 Subject: [PATCH] wip: setting up base for monitoring --- harmony/src/domain/topology/k8s_anywhere.rs | 48 --------- .../alert_channel/discord_alert_channel.rs | 80 +++++++++++++-- .../src/modules/monitoring/alert_receiver.rs | 55 +++++++++++ harmony/src/modules/monitoring/alert_rule.rs | 11 +++ harmony/src/modules/monitoring/mod.rs | 5 +- .../src/modules/monitoring/monitoring_2.rs | 59 ----------- .../modules/monitoring/monitoring_alerting.rs | 73 ++------------ harmony/src/modules/monitoring/prometheus.rs | 99 +++++++++++++++++++ .../src/modules/monitoring/scrape_target.rs | 9 ++ 9 files changed, 262 insertions(+), 177 deletions(-) create mode 100644 harmony/src/modules/monitoring/alert_receiver.rs create mode 100644 harmony/src/modules/monitoring/alert_rule.rs delete mode 100644 harmony/src/modules/monitoring/monitoring_2.rs create mode 100644 harmony/src/modules/monitoring/prometheus.rs create mode 100644 harmony/src/modules/monitoring/scrape_target.rs diff --git a/harmony/src/domain/topology/k8s_anywhere.rs b/harmony/src/domain/topology/k8s_anywhere.rs index 87d47bd..c143805 100644 --- a/harmony/src/domain/topology/k8s_anywhere.rs +++ b/harmony/src/domain/topology/k8s_anywhere.rs @@ -40,7 +40,6 @@ enum K8sSource { pub struct K8sAnywhereTopology { k8s_state: OnceCell>, tenant_manager: OnceCell, - k8s_monitor: OnceCell, config: K8sAnywhereConfig, } @@ -66,7 +65,6 @@ impl K8sAnywhereTopology { Self { k8s_state: OnceCell::new(), tenant_manager: OnceCell::new(), - k8s_monitor: OnceCell::new(), config: K8sAnywhereConfig::from_env(), } } @@ -75,7 +73,6 @@ impl K8sAnywhereTopology { Self { k8s_state: OnceCell::new(), tenant_manager: OnceCell::new(), - k8s_monitor: OnceCell::new(), config, } } @@ -206,30 +203,6 @@ impl K8sAnywhereTopology { )), } } - - async fn ensure_k8s_monitor(&self) -> Result<(), String> { - if let Some(_) = self.k8s_monitor.get() { - return Ok(()); - } - - self.k8s_monitor - .get_or_try_init(async || -> Result { - let config = K8sMonitorConfig::cluster_monitor(); - Ok(K8sMonitor { config }) - }) - .await - .unwrap(); - Ok(()) - } - - fn get_k8s_monitor(&self) -> Result<&K8sMonitor, ExecutorError> { - match self.k8s_monitor.get() { - Some(k) => Ok(k), - None => Err(ExecutorError::UnexpectedError( - "K8sMonitor not available".to_string(), - )), - } - } } pub struct K8sAnywhereConfig { @@ -281,10 +254,6 @@ impl Topology for K8sAnywhereTopology { "No K8s client could be found or installed".to_string(), ))?; - self.ensure_k8s_monitor() - .await - .map_err(|e| InterpretError::new(e))?; - self.ensure_k8s_tenant_manager() .await .map_err(|e| InterpretError::new(e))?; @@ -309,20 +278,3 @@ impl TenantManager for K8sAnywhereTopology { .await } } -#[async_trait] -impl Monitor for K8sAnywhereTopology { - async fn provision_monitor( - &self, - inventory: &Inventory, - topology: &T, - alert_receivers: Option>>, - ) -> Result { - self.get_k8s_monitor()? - .provision_monitor(inventory, topology, alert_receivers) - .await - } - - fn delete_monitor(&self) -> Result { - todo!() - } -} 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 9dc11f3..e8bca1d 100644 --- a/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs +++ b/harmony/src/modules/monitoring/alert_channel/discord_alert_channel.rs @@ -1,8 +1,76 @@ -use url::Url; +//#[derive(Debug, Clone)] +//pub struct DiscordWebhookAlertChannel { +// pub webhook_url: Url, +// pub name: String, +// pub send_resolved_notifications: bool, +//} -#[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}; + +#[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()) + } +} + + +#[derive(Debug, Clone, Serialize)] +pub struct DiscordWebhookScore { + pub config: DiscordWebhook, +} + +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 new file mode 100644 index 0000000..c8a7028 --- /dev/null +++ b/harmony/src/modules/monitoring/alert_receiver.rs @@ -0,0 +1,55 @@ +use std::fmt::Debug; + +use async_trait::async_trait; + +use crate::{ + data::{Id, Version}, + interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + inventory::Inventory, + topology::Topology, +}; + +use super::prometheus::AlertSender; + +pub trait AlertReceiver: Debug + Send + Sync { + type Sender: AlertSender; + + fn install(&self, sender: &Self::Sender) -> Result<(), String>; +} + +struct AlertReceiverConfig { + config: String, // Or whatever + sender: S, +} + +#[derive(Debug)] +pub struct AlertReceiverInterpret { + pub receiver: Box>, +} + +#[async_trait] +impl Interpret for AlertReceiverInterpret { + async fn execute( + &self, + inventory: &Inventory, + topology: &T, + ) -> Result { + 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/alert_rule.rs b/harmony/src/modules/monitoring/alert_rule.rs new file mode 100644 index 0000000..c64014c --- /dev/null +++ b/harmony/src/modules/monitoring/alert_rule.rs @@ -0,0 +1,11 @@ +use std::fmt::Debug; + +use super::prometheus::AlertSender; + +pub trait AlertRule: Debug { + type Sender: AlertSender; + + fn install(&self, sender: &Self::Sender); +} + + diff --git a/harmony/src/modules/monitoring/mod.rs b/harmony/src/modules/monitoring/mod.rs index 8baa019..070aa2e 100644 --- a/harmony/src/modules/monitoring/mod.rs +++ b/harmony/src/modules/monitoring/mod.rs @@ -1,4 +1,7 @@ pub mod alert_channel; pub mod kube_prometheus; pub mod monitoring_alerting; -mod monitoring_2; +pub mod prometheus; +pub mod alert_receiver; +pub mod alert_rule; +pub mod scrape_target; diff --git a/harmony/src/modules/monitoring/monitoring_2.rs b/harmony/src/modules/monitoring/monitoring_2.rs deleted file mode 100644 index b8e1dfc..0000000 --- a/harmony/src/modules/monitoring/monitoring_2.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::{score::Score, topology::Topology}; - -pub trait AlertSender {} - -struct Prometheus {} - -impl Prometheus { - fn configure_receiver(&self, receiver: PrometheusReceiver) -> Result<(), String> { - todo!() - } -} - -impl AlertSender for Prometheus {} - -struct DiscordWebhook; -struct PrometheusReceiver; - -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()) - } -} - -pub trait AlertReceiver { - type Sender: AlertSender; - - fn install(&self) -> Result<(), String>; -} - -struct AlertReceiverConfig { - config: String, // Or whatever - sender: S, -} - -struct DiscordWebhookScore { - config: DiscordWebhook, -} - -impl Score for DiscordWebhookScore { - fn create_interpret(&self) -> Box { - AlertReceiverInterpret { receiver: Box::new(self.config.clone())} - } - - fn name(&self) -> String { - todo!() - } -} - -struct AlertReceiverInterpret { - receiver: Box, -} diff --git a/harmony/src/modules/monitoring/monitoring_alerting.rs b/harmony/src/modules/monitoring/monitoring_alerting.rs index 1d0d48e..d170a93 100644 --- a/harmony/src/modules/monitoring/monitoring_alerting.rs +++ b/harmony/src/modules/monitoring/monitoring_alerting.rs @@ -11,74 +11,22 @@ use crate::{ topology::{HelmCommand, Topology}, }; +use super::alert_receiver::AlertReceiver; +use super::alert_rule::AlertRule; +use super::scrape_target::ScrapeTarget; + + pub trait MonitoringSystem {} -trait PrometheusReceiver { - fn get_config(&self) -> PrometheusReceiverConfig; -} - -struct PrometheusReceiverConfig { - config: Value, // either a serde Value or a more specific type that understands prometheus - // config -} - -struct PrometheusRule { - definition: String, // Not a string but an actual prometheus rule config -} - -struct PrometheusScrapeTarget { - definition: String, // Not a string but an actual prometheus scraping config -} - -pub struct PrometheusMonitoringScore { - alert_receivers: Vec>, - alert_rules: Vec>, - scrape_targets: Vec>, -} - -pub struct PrometheusMonitoringInterpret {} - -#[async_trait] -impl Interpret for PrometheusMonitoringInterpret { - async fn execute( - &self, - inventory: &Inventory, - topology: &T, - ) -> Result { - 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!() - } -} - -pub trait PrometheusCapability { - fn install_alert_receivers(&self, receivers: Vec>); - fn install_alert_rules(&self, rules: Vec>); - fn install_scrape_targets(&self, receivers: Vec>); -} #[derive(Debug, Clone, Serialize)] pub struct MonitoringAlertingScore { - alert_receivers: Vec>>, - alert_rules: Vec>>, - monitoring_targets: Vec>>, + alert_receivers: Vec>>, + alert_rules: Vec>>, + scrape_targets: Vec>>, } -impl Score for MonitoringAlertingScore { +impl Score for MonitoringAlertingScore { fn create_interpret(&self) -> Box> { Box::new(MonitoringAlertingInterpret { score: self.clone(), @@ -96,7 +44,7 @@ struct MonitoringAlertingInterpret { } #[async_trait] -impl Interpret for MonitoringAlertingInterpret { +impl Interpret for MonitoringAlertingInterpret { async fn execute( &self, inventory: &Inventory, @@ -127,4 +75,3 @@ impl Interpret for MonitoringAlertingInt todo!() } } - diff --git a/harmony/src/modules/monitoring/prometheus.rs b/harmony/src/modules/monitoring/prometheus.rs new file mode 100644 index 0000000..270fd84 --- /dev/null +++ b/harmony/src/modules/monitoring/prometheus.rs @@ -0,0 +1,99 @@ +use async_trait::async_trait; +use serde::Serialize; +use serde_value::Value; + +use crate::{ + data::{Id, Version}, + interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + inventory::Inventory, + score::Score, + topology::Topology, +}; +use std::fmt::Debug; + +pub trait AlertSender {} + +#[derive(Debug, Clone, Serialize)] +pub struct Prometheus {} + +impl Prometheus { + pub fn configure_receiver(&self, receiver: PrometheusReceiver) -> Result<(), String> { + todo!() + } + pub fn configure_rule(&self, rule: PrometheusRule) { + todo!() + } + pub fn configure_scrape_target(&self, target: PrometheusScrapeTarget) { + todo!() + } +} + +pub trait PrometheusCapability { + fn install_alert_receivers(&self, receivers: Vec>); + fn install_alert_rules(&self, rules: Vec>); + fn install_scrape_targets(&self, receivers: Vec>); +} + +impl AlertSender for Prometheus {} + +pub trait PrometheusReceiver{ + fn get_prometheus_config(&self) -> PrometheusReceiverConfig; +} + +pub struct PrometheusReceiverConfig { + config: Value, // either a serde Value or a more specific type that understands prometheus + // config +} + +pub trait PrometheusRule{ + fn get_prometheus_config(&self) -> PrometheusRuleConfig; +} + +pub struct PrometheusRuleConfig { + pub definition: String, // Not a string but an actual prometheus rule config +} + +pub trait PrometheusScrapeTarget { + fn get_prometheus_config(&self) -> PrometheusScrapeTargetConfig; +} + +pub struct PrometheusScrapeTargetConfig { + pub definition: String, // Not a string but an actual prometheus scraping config +} + +pub struct PrometheusMonitoringScore { + alert_receivers: Vec>, + alert_rules: Vec>, + scrape_targets: Vec>, +} + +#[derive(Debug)] +pub struct PrometheusMonitoringInterpret {} + +#[async_trait] +impl Interpret for PrometheusMonitoringInterpret { + async fn execute( + &self, + inventory: &Inventory, + topology: &T, + ) -> Result { + 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/scrape_target.rs b/harmony/src/modules/monitoring/scrape_target.rs new file mode 100644 index 0000000..954bf0c --- /dev/null +++ b/harmony/src/modules/monitoring/scrape_target.rs @@ -0,0 +1,9 @@ +use std::fmt::Debug; + +use super::prometheus::AlertSender; + +pub trait ScrapeTarget: Debug { + type Sender: AlertSender; + + fn install(&self, sender: &Self::Sender); +}