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
This commit is contained in:
parent
ba536885bd
commit
527b88ce3b
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -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"
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "monitoring"
|
||||
name = "example-monitoring"
|
||||
edition = "2024"
|
||||
version.workspace = true
|
||||
readme.workspace = true
|
||||
|
@ -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::<K8sAnywhereTopology>::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();
|
||||
}
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
|
86
harmony/src/modules/monitoring/alert_score.rs
Normal file
86
harmony/src/modules/monitoring/alert_score.rs
Normal file
@ -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<S: AlertSender>: std::fmt::Debug + Send + Sync {
|
||||
fn install(&self, sender: &S) -> Result<(), InterpretError>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct PrometheusAlertingScore {
|
||||
pub receivers: Vec<Box<dyn AlertReceiver<Prometheus>>>,
|
||||
}
|
||||
|
||||
impl Serialize for Box<dyn AlertReceiver<Prometheus>> {
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl Clone for Box<dyn AlertReceiver<Prometheus>> {
|
||||
fn clone(&self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Topology + HelmCommand> Score<T> for PrometheusAlertingScore {
|
||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
|
||||
Box::new(AlertingInterpret { sender: Prometheus {}, receivers: todo!() })
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"PrometheusAlertingScore".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Prometheus;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AlertingInterpret<S: AlertSender> {
|
||||
pub sender: S,
|
||||
pub receivers: Vec<Box<dyn AlertReceiver<S>>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S: AlertSender, T: Topology> Interpret<T> for AlertingInterpret<S> {
|
||||
#[must_use]
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
|
||||
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<Id> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -5,3 +5,4 @@ pub mod kube_prometheus;
|
||||
pub mod monitoring_alerting;
|
||||
pub mod prometheus;
|
||||
pub mod scrape_target;
|
||||
pub mod alert_score;
|
||||
|
@ -27,11 +27,6 @@ pub struct MonitoringAlertingScore<M: MonitoringSystem> {
|
||||
pub scrape_targets: Vec<Box<dyn ScrapeTarget<M = M>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MonitoringConfig<M: MonitoringSystem> {
|
||||
receivers: Vec<Box<dyn AlertReceiver<M = M>>>,
|
||||
}
|
||||
|
||||
impl<M: MonitoringSystem> Clone for Box<dyn AlertReceiver<M = M>> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_box()
|
||||
@ -49,7 +44,7 @@ impl<M: MonitoringSystem> Clone for Box<dyn ScrapeTarget<M = M>> {
|
||||
}
|
||||
|
||||
impl<M: MonitoringSystem> Serialize for MonitoringAlertingScore<M> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
@ -84,11 +79,21 @@ impl<M: MonitoringSystem + Installable, T: Topology> Interpret<T>
|
||||
{
|
||||
async fn execute(
|
||||
&self,
|
||||
inventory: &Inventory,
|
||||
topology: &T,
|
||||
_inventory: &Inventory,
|
||||
_topology: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
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<Sender = Prometheus>)
|
||||
|
|
||||
Prometheus (AlertSender + Scraper + Installable<T: HelmCommand>)
|
||||
^
|
||||
MonitoringScore {{ alert_rules, alert_receivers, scrape_endpoints }}
|
||||
(Interpret<T: Topology + Installer
|
||||
|
||||
")
|
||||
}
|
||||
|
||||
fn get_name(&self) -> InterpretName {
|
||||
@ -108,8 +113,3 @@ impl<M: MonitoringSystem + Installable, T: Topology> Interpret<T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MonitoringSystem> MonitoringAlertingInterpret<M> {
|
||||
fn build_config(&self) -> MonitoringConfig<M> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -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>) {
|
||||
|
Loading…
Reference in New Issue
Block a user