feat: Initial setup for monitoring and alerting #48

Merged
wjro merged 7 commits from feat/monitor into master 2025-06-03 18:17:17 +00:00
6 changed files with 109 additions and 5 deletions
Showing only changes of commit b631e8ccbb - Show all commits

View File

@@ -49,3 +49,4 @@ fqdn = { version = "0.4.6", features = [
"serde",
] }
temp-dir = "0.1.14"
dyn-clone = "1.0.19"

View File

@@ -15,11 +15,9 @@ use crate::{
};
use super::{
HelmCommand, K8sclient, Topology,
k8s::K8sClient,
tenant::{
ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy, k8s::K8sTenantManager,
},
k8s::K8sClient, oberservability::notification_adapter_deployer::NotificationAdapterDeployer, tenant::{
k8s::K8sTenantManager, ResourceLimits, TenantConfig, TenantManager, TenantNetworkPolicy
}, HelmCommand, K8sclient, Topology
};
struct K8sState {
@@ -263,3 +261,19 @@ impl TenantManager for K8sAnywhereTopology {
.await
}
}
#[async_trait]
impl NotificationAdapterDeployer for K8sAnywhereTopology {
fn deploy_notification_adapter(
&self,
_notification_adapter_id: &str,
) -> Result<Outcome, InterpretError> {
todo!()
}
fn remove_notification_adapter(
&self,
_notification_adapter_id: &str,
) -> Result<Outcome, InterpretError> {
todo!()
}
}

View File

@@ -4,6 +4,7 @@ mod http;
mod k8s_anywhere;
mod localhost;
pub mod tenant;
pub mod oberservability;
pub use k8s_anywhere::*;
pub use localhost::*;
pub mod k8s;

View File

@@ -0,0 +1,16 @@
use monitoring::AlertChannelConfig;
pub mod monitoring;
pub mod notification_adapter_deployer;
pub enum MonitoringBackendType {
KubePrometheus,
}
pub struct MonitorConfig {
pub backend: MonitoringBackendType,
pub alert_channels: Vec<Box<dyn AlertChannelConfig>>,
}

View File

@@ -0,0 +1,60 @@
use async_trait::async_trait;
use std::fmt::Debug;
use dyn_clone::DynClone;
use serde_json::Value;
use crate::interpret::InterpretError;
use crate::{
interpret::Outcome,
topology::Topology,
};
Review

This rustdoc is pretty good to explain the abstraction, but giving a concrete example such as Prometheus would make a complete understanding much easier. Even I still have a bit of trouble to figure it out as-is.

This rustdoc is pretty good to explain the abstraction, but giving a concrete example such as Prometheus would make a complete understanding much easier. Even I still have a bit of trouble to figure it out as-is.
use super::notification_adapter_deployer::NotificationAdapterDeployer;
use super::{MonitorConfig, MonitoringBackendType};
#[async_trait]
pub trait Monitor<T: Topology + NotificationAdapterDeployer> {
async fn provision_monitor(
&self,
topology: &T,
monitor_config: &MonitorConfig,
) -> Result<Outcome, InterpretError>;
async fn delete_monitor(
&self,
topolgy: &T,
monitor_config: &MonitorConfig,
) -> Result<Outcome, InterpretError>;
async fn configure_alerting(
&self,
topology: &T,
monitor_config: &MonitorConfig,
) -> Result<Outcome, InterpretError>;
async fn ensure_alert_channel_dependencies(
&self,
topology: &T,
monitor_config: &MonitorConfig,
) -> Result<Outcome, InterpretError> {
for channel in &monitor_config.alert_channels {
if let Some(notification_adapter_id) =
channel.requires_external_alert_channel_adapter(&monitor_config.backend)
{
topology.deploy_notification_adapter(
&notification_adapter_id.as_ref(),
)?;
}
}
Ok(Outcome::success(format!("deployed alert channels {:?}", &monitor_config.alert_channels)))
}
}
pub trait AlertChannelConfig: Debug + DynClone + Send + Sync {
fn build_backend_integration_config(&self, backend: &MonitoringBackendType) -> Result<Value, InterpretError>;
fn requires_external_alert_channel_adapter(&self, backend: &MonitoringBackendType) -> Option<String>;
}

View File

@@ -0,0 +1,12 @@
use crate::interpret::{InterpretError, Outcome};
pub trait NotificationAdapterDeployer {
fn deploy_notification_adapter(
&self,
notification_adapter_id: &str,
) -> Result<Outcome, InterpretError>;
fn remove_notification_adapter(
&self,
notication_adapter_id: &str,
) -> Result<Outcome, InterpretError>;
}