use prometheus_client::{
encoding::{EncodeLabelSet, EncodeMetric},
metrics::{counter::Counter, TypedMetric},
};
use std::hash::Hash;
use crate::{
traits::{GaugeValue, HistogramValue},
wrappers::{Family, Gauge, Histogram, Info},
Buckets,
};
#[derive(Debug, Clone, Copy)]
pub struct MetricBuilder<B = (), L = ()> {
buckets: B,
labels: L,
}
impl MetricBuilder {
pub const fn new() -> Self {
Self {
buckets: (),
labels: (),
}
}
}
impl<L> MetricBuilder<(), L> {
pub fn with_buckets(self, buckets: impl Into<Buckets>) -> MetricBuilder<Buckets, L> {
MetricBuilder {
buckets: buckets.into(),
labels: self.labels,
}
}
}
impl<B> MetricBuilder<B> {
pub fn with_labels<L>(self, labels: L) -> MetricBuilder<B, L> {
MetricBuilder {
buckets: self.buckets,
labels,
}
}
}
pub trait BuildMetric: 'static + Sized + EncodeMetric + TypedMetric {
type Builder: Copy;
fn build(builder: Self::Builder) -> Self;
}
impl<N, A> BuildMetric for Counter<N, A>
where
Counter<N, A>: 'static + EncodeMetric + Default,
{
type Builder = MetricBuilder;
fn build(_builder: Self::Builder) -> Self {
Self::default()
}
}
impl<V: GaugeValue> BuildMetric for Gauge<V> {
type Builder = MetricBuilder;
fn build(_builder: Self::Builder) -> Self {
Self::default()
}
}
impl<V: HistogramValue> BuildMetric for Histogram<V> {
type Builder = MetricBuilder<Buckets>;
fn build(builder: Self::Builder) -> Self {
Histogram::new(builder.buckets)
}
}
impl<S: 'static + EncodeLabelSet> BuildMetric for Info<S> {
type Builder = MetricBuilder;
fn build(_builder: Self::Builder) -> Self {
Self::default()
}
}
impl<S, M, B, L> BuildMetric for Family<S, M, L>
where
S: 'static + Clone + Eq + Hash,
M: BuildMetric<Builder = MetricBuilder<B, ()>>,
B: Copy,
L: 'static + Copy,
Family<S, M, L>: EncodeMetric,
{
type Builder = MetricBuilder<B, L>;
fn build(builder: Self::Builder) -> Self {
let item_builder = MetricBuilder {
buckets: builder.buckets,
labels: (),
};
Family::new(item_builder, builder.labels)
}
}