wip: setting up base for monitoring
This commit is contained in:
parent
c16276b62b
commit
f6c146b14b
@ -40,7 +40,6 @@ enum K8sSource {
|
|||||||
pub struct K8sAnywhereTopology {
|
pub struct K8sAnywhereTopology {
|
||||||
k8s_state: OnceCell<Option<K8sState>>,
|
k8s_state: OnceCell<Option<K8sState>>,
|
||||||
tenant_manager: OnceCell<K8sTenantManager>,
|
tenant_manager: OnceCell<K8sTenantManager>,
|
||||||
k8s_monitor: OnceCell<K8sMonitor>,
|
|
||||||
config: K8sAnywhereConfig,
|
config: K8sAnywhereConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +65,6 @@ impl K8sAnywhereTopology {
|
|||||||
Self {
|
Self {
|
||||||
k8s_state: OnceCell::new(),
|
k8s_state: OnceCell::new(),
|
||||||
tenant_manager: OnceCell::new(),
|
tenant_manager: OnceCell::new(),
|
||||||
k8s_monitor: OnceCell::new(),
|
|
||||||
config: K8sAnywhereConfig::from_env(),
|
config: K8sAnywhereConfig::from_env(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +73,6 @@ impl K8sAnywhereTopology {
|
|||||||
Self {
|
Self {
|
||||||
k8s_state: OnceCell::new(),
|
k8s_state: OnceCell::new(),
|
||||||
tenant_manager: OnceCell::new(),
|
tenant_manager: OnceCell::new(),
|
||||||
k8s_monitor: OnceCell::new(),
|
|
||||||
config,
|
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<K8sMonitor, String> {
|
|
||||||
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 {
|
pub struct K8sAnywhereConfig {
|
||||||
@ -281,10 +254,6 @@ impl Topology for K8sAnywhereTopology {
|
|||||||
"No K8s client could be found or installed".to_string(),
|
"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()
|
self.ensure_k8s_tenant_manager()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| InterpretError::new(e))?;
|
.map_err(|e| InterpretError::new(e))?;
|
||||||
@ -309,20 +278,3 @@ impl TenantManager for K8sAnywhereTopology {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[async_trait]
|
|
||||||
impl Monitor for K8sAnywhereTopology {
|
|
||||||
async fn provision_monitor<T: Topology + HelmCommand>(
|
|
||||||
&self,
|
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
alert_receivers: Option<Vec<Box<dyn AlertChannelConfig>>>,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
self.get_k8s_monitor()?
|
|
||||||
.provision_monitor(inventory, topology, alert_receivers)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
fn delete_monitor(&self) -> Result<Outcome, InterpretError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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)]
|
use serde::Serialize;
|
||||||
pub struct DiscordWebhookAlertChannel {
|
|
||||||
pub webhook_url: Url,
|
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};
|
||||||
pub name: String,
|
|
||||||
pub send_resolved_notifications: bool,
|
#[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<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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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!() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
55
harmony/src/modules/monitoring/alert_receiver.rs
Normal file
55
harmony/src/modules/monitoring/alert_receiver.rs
Normal file
@ -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<S: AlertSender> {
|
||||||
|
config: String, // Or whatever
|
||||||
|
sender: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AlertReceiverInterpret {
|
||||||
|
pub receiver: Box<dyn AlertReceiver<Sender = dyn AlertSender>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Topology> Interpret<T> for AlertReceiverInterpret {
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
inventory: &Inventory,
|
||||||
|
topology: &T,
|
||||||
|
) -> Result<Outcome, InterpretError> {
|
||||||
|
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!()
|
||||||
|
}
|
||||||
|
}
|
11
harmony/src/modules/monitoring/alert_rule.rs
Normal file
11
harmony/src/modules/monitoring/alert_rule.rs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
|||||||
pub mod alert_channel;
|
pub mod alert_channel;
|
||||||
pub mod kube_prometheus;
|
pub mod kube_prometheus;
|
||||||
pub mod monitoring_alerting;
|
pub mod monitoring_alerting;
|
||||||
mod monitoring_2;
|
pub mod prometheus;
|
||||||
|
pub mod alert_receiver;
|
||||||
|
pub mod alert_rule;
|
||||||
|
pub mod scrape_target;
|
||||||
|
@ -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<S: AlertSender> {
|
|
||||||
config: String, // Or whatever
|
|
||||||
sender: S,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DiscordWebhookScore {
|
|
||||||
config: DiscordWebhook,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology> Score<T> for DiscordWebhookScore {
|
|
||||||
fn create_interpret(&self) -> Box<AlertReceiverInterpret> {
|
|
||||||
AlertReceiverInterpret { receiver: Box::new(self.config.clone())}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AlertReceiverInterpret {
|
|
||||||
receiver: Box<dyn AlertReceiver>,
|
|
||||||
}
|
|
@ -11,74 +11,22 @@ use crate::{
|
|||||||
topology::{HelmCommand, Topology},
|
topology::{HelmCommand, Topology},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::alert_receiver::AlertReceiver;
|
||||||
|
use super::alert_rule::AlertRule;
|
||||||
|
use super::scrape_target::ScrapeTarget;
|
||||||
|
|
||||||
|
|
||||||
pub trait MonitoringSystem {}
|
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<Box<dyn PrometheusReceiver>>,
|
|
||||||
alert_rules: Vec<Box<PrometheusRule>>,
|
|
||||||
scrape_targets: Vec<Box<PrometheusScrapeTarget>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PrometheusMonitoringInterpret {}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T: Topology + PrometheusCapability> Interpret<T> for PrometheusMonitoringInterpret {
|
|
||||||
async fn execute(
|
|
||||||
&self,
|
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
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!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PrometheusCapability {
|
|
||||||
fn install_alert_receivers(&self, receivers: Vec<Box<dyn PrometheusReceiver>>);
|
|
||||||
fn install_alert_rules(&self, rules: Vec<Box<PrometheusRule>>);
|
|
||||||
fn install_scrape_targets(&self, receivers: Vec<Box<PrometheusScrapeTarget>>);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct MonitoringAlertingScore<M: MonitoringSystem> {
|
pub struct MonitoringAlertingScore<M: MonitoringSystem> {
|
||||||
alert_receivers: Vec<Box<dyn AlertReceiver<M>>>,
|
alert_receivers: Vec<Box<dyn AlertReceiver<Sender = M>>>,
|
||||||
alert_rules: Vec<Box<dyn AlertRules<M>>>,
|
alert_rules: Vec<Box<dyn AlertRule<Sender = M>>>,
|
||||||
monitoring_targets: Vec<Box<dyn MonitoringTarget<M>>>,
|
scrape_targets: Vec<Box<dyn ScrapeTarget<Sender = M>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + Monitor> Score<T> for MonitoringAlertingScore {
|
impl<T: Topology, M: MonitoringSystem> Score<T> for MonitoringAlertingScore<M> {
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
Box::new(MonitoringAlertingInterpret {
|
Box::new(MonitoringAlertingInterpret {
|
||||||
score: self.clone(),
|
score: self.clone(),
|
||||||
@ -96,7 +44,7 @@ struct MonitoringAlertingInterpret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T: Topology + HelmCommand + Monitor> Interpret<T> for MonitoringAlertingInterpret {
|
impl<T: Topology> Interpret<T> for MonitoringAlertingInterpret {
|
||||||
async fn execute(
|
async fn execute(
|
||||||
&self,
|
&self,
|
||||||
inventory: &Inventory,
|
inventory: &Inventory,
|
||||||
@ -127,4 +75,3 @@ impl<T: Topology + HelmCommand + Monitor> Interpret<T> for MonitoringAlertingInt
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
harmony/src/modules/monitoring/prometheus.rs
Normal file
99
harmony/src/modules/monitoring/prometheus.rs
Normal file
@ -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<Box<dyn PrometheusReceiver>>);
|
||||||
|
fn install_alert_rules(&self, rules: Vec<Box<dyn PrometheusRule>>);
|
||||||
|
fn install_scrape_targets(&self, receivers: Vec<Box<dyn PrometheusScrapeTarget>>);
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Box<PrometheusReceiverConfig>>,
|
||||||
|
alert_rules: Vec<Box<PrometheusRuleConfig>>,
|
||||||
|
scrape_targets: Vec<Box<PrometheusScrapeTargetConfig>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PrometheusMonitoringInterpret {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Topology + PrometheusCapability> Interpret<T> for PrometheusMonitoringInterpret {
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
inventory: &Inventory,
|
||||||
|
topology: &T,
|
||||||
|
) -> Result<Outcome, InterpretError> {
|
||||||
|
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
harmony/src/modules/monitoring/scrape_target.rs
Normal file
9
harmony/src/modules/monitoring/scrape_target.rs
Normal file
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user