use std::collections::HashMap;
use std::future::Future;
use url::Url;
use crate::ConvertMetrics;
use crate::error::Result;
use crate::utils::PushType;
use crate::utils::create_metrics_job_url;
#[derive(Debug)]
pub struct MetricsPusher<P, CM, MF, C, B>
where
P: Push<B>,
CM: ConvertMetrics<MF, C, B>,
{
push_client: P,
metrics_converter: CM,
url: Url,
mf: std::marker::PhantomData<MF>,
c: std::marker::PhantomData<C>,
b: std::marker::PhantomData<B>,
}
pub trait Push<B> {
fn push_all(
&self,
url: &Url,
body: B,
content_type: &str,
) -> impl Future<Output = Result<()>> + Send;
fn push_add(&self, url: &Url, body: B, content_type: &str) -> impl Future<Output = Result<()>>;
}
impl<P, CM, MF, C, B> MetricsPusher<P, CM, MF, C, B>
where
P: Push<B>,
CM: ConvertMetrics<MF, C, B>,
{
pub fn new(
push_client: P,
metrics_converter: CM,
url: &Url,
) -> Result<MetricsPusher<P, CM, MF, C, B>> {
let url = create_metrics_job_url(url)?;
Ok(Self {
push_client,
metrics_converter,
url,
mf: std::marker::PhantomData,
c: std::marker::PhantomData,
b: std::marker::PhantomData,
})
}
pub async fn push_all(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
metric_families: MF,
) -> Result<()> {
self.push(job, grouping, metric_families, PushType::All)
.await
}
pub async fn push_add(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
metric_families: MF,
) -> Result<()> {
self.push(job, grouping, metric_families, PushType::Add)
.await
}
pub async fn push_all_collectors(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
collectors: C,
) -> Result<()> {
self.push_collectors(job, grouping, collectors, PushType::All)
.await
}
pub async fn push_add_collectors(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
collectors: C,
) -> Result<()> {
self.push_collectors(job, grouping, collectors, PushType::Add)
.await
}
async fn push_collectors(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
collectors: C,
push_type: PushType,
) -> Result<()> {
let metric_families = self.metrics_converter.metrics_from(collectors)?;
self.push(job, grouping, metric_families, push_type).await
}
async fn push(
&self,
job: &str,
grouping: &HashMap<&str, &str>,
metric_families: MF,
push_type: PushType,
) -> Result<()> {
let (url, encoded_metrics, content_type) = self.metrics_converter.create_push_details(
job,
&self.url,
grouping,
metric_families,
)?;
match push_type {
PushType::Add => {
self.push_client
.push_add(&url, encoded_metrics, &content_type)
.await
}
PushType::All => {
self.push_client
.push_all(&url, encoded_metrics, &content_type)
.await
}
}
}
}