wip: Monitoring architecture becoming clearer, added adr/010-monitoring-alerting/architecture.rs that demonstrates how we designed the monitoring stack to be fully extensible by other crates
This commit is contained in:
parent
9412c0529a
commit
c6a39a39a1
73
adr/010-monitoring-alerting/architecture.rs
Normal file
73
adr/010-monitoring-alerting/architecture.rs
Normal file
@ -0,0 +1,73 @@
|
||||
pub trait MonitoringSystem {}
|
||||
|
||||
// 1. Modified AlertReceiver trait:
|
||||
// - Removed the problematic `clone` method.
|
||||
// - Added `box_clone` which returns a Box<dyn AlertReceiver>.
|
||||
pub trait AlertReceiver {
|
||||
type M: MonitoringSystem;
|
||||
fn install(&self, sender: &Self::M) -> Result<(), String>;
|
||||
// This method allows concrete types to clone themselves into a Box<dyn AlertReceiver>
|
||||
fn box_clone(&self) -> Box<dyn AlertReceiver<M = Self::M>>;
|
||||
}
|
||||
#[derive(Clone)]
|
||||
struct Prometheus{}
|
||||
impl MonitoringSystem for Prometheus {}
|
||||
|
||||
#[derive(Clone)] // Keep derive(Clone) for DiscordWebhook itself
|
||||
struct DiscordWebhook{}
|
||||
|
||||
impl AlertReceiver for DiscordWebhook {
|
||||
type M = Prometheus;
|
||||
fn install(&self, sender: &Self::M) -> Result<(), String> {
|
||||
// Placeholder for actual installation logic
|
||||
println!("DiscordWebhook installed for Prometheus monitoring.");
|
||||
Ok(())
|
||||
}
|
||||
// 2. Implement `box_clone` for DiscordWebhook:
|
||||
// This uses the derived `Clone` for DiscordWebhook to create a new boxed instance.
|
||||
fn box_clone(&self) -> Box<dyn AlertReceiver<M = Self::M>> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Implement `std::clone::Clone` for `Box<dyn AlertReceiver<M= M>>`:
|
||||
// This allows `Box<dyn AlertReceiver>` to be cloned.
|
||||
// The `+ 'static` lifetime bound is often necessary for trait objects stored in collections,
|
||||
// ensuring they live long enough.
|
||||
impl<M: MonitoringSystem + 'static> Clone for Box<dyn AlertReceiver<M= M>> {
|
||||
fn clone(&self) -> Self {
|
||||
self.box_clone() // Call the custom `box_clone` method
|
||||
}
|
||||
}
|
||||
|
||||
// MonitoringConfig can now derive Clone because its `receivers` field
|
||||
// (Vec<Box<dyn AlertReceiver<M = M>>>) is now cloneable.
|
||||
#[derive(Clone)]
|
||||
struct MonitoringConfig <M: MonitoringSystem + 'static>{
|
||||
receivers: Vec<Box<dyn AlertReceiver<M = M>>>
|
||||
}
|
||||
|
||||
// Example usage to demonstrate compilation and functionality
|
||||
fn main() {
|
||||
let prometheus_instance = Prometheus{};
|
||||
let discord_webhook_instance = DiscordWebhook{};
|
||||
|
||||
let mut config = MonitoringConfig {
|
||||
receivers: Vec::new()
|
||||
};
|
||||
|
||||
// Create a boxed alert receiver
|
||||
let boxed_receiver: Box<dyn AlertReceiver<M = Prometheus>> = Box::new(discord_webhook_instance);
|
||||
config.receivers.push(boxed_receiver);
|
||||
|
||||
// Clone the config, which will now correctly clone the boxed receiver
|
||||
let cloned_config = config.clone();
|
||||
|
||||
println!("Original config has {} receivers.", config.receivers.len());
|
||||
println!("Cloned config has {} receivers.", cloned_config.receivers.len());
|
||||
|
||||
// Example of using the installed receiver
|
||||
if let Some(receiver) = config.receivers.get(0) {
|
||||
let _ = receiver.install(&prometheus_instance);
|
||||
}
|
||||
}
|
@ -2,7 +2,13 @@ use harmony::{
|
||||
data::Version,
|
||||
inventory::Inventory,
|
||||
maestro::Maestro,
|
||||
modules::{lamp::{LAMPConfig, LAMPScore}, monitoring::monitoring_alerting::MonitoringAlertingScore},
|
||||
modules::{
|
||||
lamp::{LAMPConfig, LAMPScore},
|
||||
monitoring::{
|
||||
alert_channel::discord_alert_channel::DiscordWebhook,
|
||||
monitoring_alerting::MonitoringAlertingScore,
|
||||
},
|
||||
},
|
||||
topology::{K8sAnywhereTopology, Url},
|
||||
};
|
||||
|
||||
@ -29,7 +35,15 @@ async fn main() {
|
||||
},
|
||||
};
|
||||
|
||||
let monitoring = MonitoringAlertingScore { alert_channel_configs: todo!() };
|
||||
let monitoring = MonitoringAlertingScore {
|
||||
alert_receivers: vec![Box::new(DiscordWebhook {
|
||||
url: Url::Url(url::Url::parse("https://discord.idonotexist.com").unwrap()),
|
||||
// TODO write url macro
|
||||
// url: url!("https://discord.idonotexist.com"),
|
||||
})],
|
||||
alert_rules: vec![],
|
||||
scrape_targets: vec![],
|
||||
};
|
||||
|
||||
// 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
|
||||
@ -42,7 +56,8 @@ async fn main() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
maestro.register_all(vec![Box::new(lamp_stack)]);
|
||||
// maestro.register_all(vec![Box::new(lamp_stack)]);
|
||||
maestro.register_all(vec![Box::new(monitoring)]);
|
||||
// Here we bootstrap the CLI, this gives some nice features if you need them
|
||||
harmony_cli::init(maestro, None).await.unwrap();
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
interpret::Interpret,
|
||||
modules::monitoring::{
|
||||
alert_receiver::{AlertReceiver, AlertReceiverInterpret},
|
||||
alert_receiver::AlertReceiver,
|
||||
prometheus::{Prometheus, PrometheusReceiver},
|
||||
},
|
||||
score::Score,
|
||||
topology::Topology,
|
||||
topology::Url,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
struct DiscordWebhook;
|
||||
pub struct DiscordWebhook {
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
impl AlertReceiver for DiscordWebhook {
|
||||
type Sender = Prometheus;
|
||||
@ -19,6 +19,12 @@ impl AlertReceiver for DiscordWebhook {
|
||||
fn install(&self, sender: &Self::Sender) -> Result<(), String> {
|
||||
sender.configure_receiver(Box::new(self))
|
||||
}
|
||||
|
||||
fn clone(&self) -> Self
|
||||
where
|
||||
Self: Sized {
|
||||
<Self as Clone>::clone(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrometheusReceiver for DiscordWebhook {
|
||||
@ -29,19 +35,19 @@ impl PrometheusReceiver for DiscordWebhook {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct DiscordWebhookScore {
|
||||
pub config: DiscordWebhook,
|
||||
}
|
||||
|
||||
impl<T: Topology> Score<T> for DiscordWebhookScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(AlertReceiverInterpret {
|
||||
receiver: Box::new(self.config.clone()),
|
||||
})
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
// #[derive(Debug, Clone, Serialize)]
|
||||
// pub struct DiscordWebhookScore {
|
||||
// pub config: DiscordWebhook,
|
||||
// }
|
||||
//
|
||||
// impl<T: Topology> Score<T> for DiscordWebhookScore {
|
||||
// fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
// Box::new(AlertReceiverInterpret {
|
||||
// receiver: Box::new(self.config.clone()),
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// fn name(&self) -> String {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
@ -9,12 +9,13 @@ use crate::{
|
||||
topology::Topology,
|
||||
};
|
||||
|
||||
use super::{monitoring_alerting::CloneBox, prometheus::AlertSender};
|
||||
use super::prometheus::AlertSender;
|
||||
|
||||
pub trait AlertReceiver: Debug + Send + Sync + CloneBox {
|
||||
pub trait AlertReceiver: Debug + Send + Sync {
|
||||
type Sender: AlertSender;
|
||||
|
||||
fn install(&self, sender: &Self::Sender) -> Result<(), String>;
|
||||
fn clone_box(&self) -> Box<dyn AlertReceiver<Sender = Self::Sender>>;
|
||||
}
|
||||
|
||||
struct AlertReceiverConfig<S: AlertSender> {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use dyn_clone::DynClone;
|
||||
|
||||
use super::prometheus::AlertSender;
|
||||
|
||||
pub trait AlertRule: Debug + Send + Sync {
|
||||
pub trait AlertRule: Debug + Send + Sync + DynClone {
|
||||
type Sender: AlertSender;
|
||||
|
||||
fn install(&self, sender: &Self::Sender);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub mod alert_channel;
|
||||
pub mod alert_receiver;
|
||||
pub mod alert_rule;
|
||||
pub mod kube_prometheus;
|
||||
pub mod monitoring_alerting;
|
||||
pub mod prometheus;
|
||||
pub mod alert_receiver;
|
||||
pub mod alert_rule;
|
||||
pub mod scrape_target;
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
topology::Topology,
|
||||
};
|
||||
|
||||
use super::alert_receiver::AlertReceiver;
|
||||
use super::{alert_receiver::AlertReceiver, prometheus::AlertSender};
|
||||
use super::alert_rule::AlertRule;
|
||||
use super::scrape_target::ScrapeTarget;
|
||||
|
||||
@ -19,15 +19,34 @@ pub trait MonitoringSystem: std::fmt::Debug + Clone + Serialize + 'static {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MonitoringAlertingScore<M: MonitoringSystem> {
|
||||
alert_receivers: Arc<Vec<Box<dyn AlertReceiver<Sender = M>>>>,
|
||||
alert_rules: Arc<Vec<Box<dyn AlertRule<Sender = M>>>>,
|
||||
scrape_targets: Arc<Vec<Box<dyn ScrapeTarget<Sender = M>>>>,
|
||||
pub alert_receivers: Vec<Box<dyn AlertReceiver<Sender = M>>>,
|
||||
pub alert_rules: Vec<Box<dyn AlertRule<Sender = M>>>,
|
||||
pub scrape_targets: Vec<Box<dyn ScrapeTarget<Sender = M>>>,
|
||||
}
|
||||
|
||||
impl <M: MonitoringSystem> Serialize for MonitoringAlertingScore<M> {
|
||||
|
||||
impl <M: MonitoringSystem + AlertSender> Clone for Box<dyn AlertReceiver<Sender = M>>{
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
impl <M: MonitoringSystem> Clone for Box<dyn AlertRule<Sender = M>>{
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl <M: MonitoringSystem> Clone for Box<dyn ScrapeTarget<Sender = M>>{
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<M: MonitoringSystem> Serialize for MonitoringAlertingScore<M> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer {
|
||||
S: serde::Serializer,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -75,16 +94,3 @@ impl<M: MonitoringSystem, T: Topology> Interpret<T> for MonitoringAlertingInterp
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CloneBox {
|
||||
fn clone_box(&self) -> Box<dyn CloneBox>;
|
||||
}
|
||||
|
||||
impl<C> CloneBox for C
|
||||
where
|
||||
C: Clone + 'static,
|
||||
{
|
||||
fn clone_box(&self) -> Box<dyn CloneBox> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,18 @@ use crate::{
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::monitoring_alerting::MonitoringSystem;
|
||||
|
||||
pub trait AlertSender: std::fmt::Debug {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Prometheus {}
|
||||
|
||||
impl Prometheus {
|
||||
pub fn configure_receiver(&self, _receiver: Box<&dyn PrometheusReceiver>) -> Result<(), String> {
|
||||
pub fn configure_receiver(
|
||||
&self,
|
||||
_receiver: Box<&dyn PrometheusReceiver>,
|
||||
) -> Result<(), String> {
|
||||
todo!()
|
||||
}
|
||||
pub fn configure_rule(&self, _rule: Box<&dyn PrometheusRule>) {
|
||||
@ -27,6 +32,8 @@ impl Prometheus {
|
||||
}
|
||||
}
|
||||
|
||||
impl MonitoringSystem for Prometheus {}
|
||||
|
||||
pub trait PrometheusCapability {
|
||||
fn install_alert_receivers(&self, receivers: Vec<Box<dyn PrometheusReceiver>>);
|
||||
fn install_alert_rules(&self, rules: Vec<Box<dyn PrometheusRule>>);
|
||||
|
@ -1,9 +1,12 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use dyn_clone::DynClone;
|
||||
|
||||
use super::prometheus::AlertSender;
|
||||
|
||||
pub trait ScrapeTarget: Debug + Send + Sync {
|
||||
pub trait ScrapeTarget: Debug + Send + Sync + DynClone {
|
||||
type Sender: AlertSender;
|
||||
|
||||
fn install(&self, sender: &Self::Sender);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user