prometheus / client_rust

Prometheus / OpenMetrics client library in Rust
Apache License 2.0
484 stars 80 forks source link

feat: derive register logic on struct of metrics #140

Open mxinden opened 1 year ago

mxinden commented 1 year ago

One oftentimes has a struct of metrics like:

struct Metrics {
    a: Counter,
    b: Gauge,
}

Code to register the metrics in Metrics with a Registry could be generated via a derive macro on Metrics.

#[derive(Register)]
struct Metrics {
    /// My Gauge tracking the number of xxx
    a: Counter,
    /// My Counter, tracking the event xxx
    #[prometheus-unit(Seconds)]
    b: Gauge,
}

Where the Register trait is something along the lines of:

trait Register {
  fn create_and_register(registry: &mut Registry) -> Self;
}
Hackzzila commented 3 months ago

I think this is a great idea! I actually implemented this myself for a project before coming across this issue. I implemented it a little differently to allow for nested structs.

pub trait Register {
    fn register(self, registry: &mut Registry);
}

pub trait RegisterField {
    fn register_field(
        self,
        name: impl Into<String>,
        help: impl Into<String>,
        registry: &mut Registry,
    );
}

impl<T: Metric> RegisterField for T {
    fn register_field(
        self,
        name: impl Into<String>,
        help: impl Into<String>,
        registry: &mut Registry,
    ) {
        registry.register(name, help, self);
    }
}

Example:

#[derive(Debug, Clone, Register)]
pub struct Metrics {
    pub foo: FooMetrics,
}

#[derive(Debug, Clone, Default, Register)]
pub struct FooMetrics {
    // This is registered as foo_counter by default
    pub messages: Counter,
}

If this is still wanted, we can decide on specifics and I can make a PR!

mxinden commented 3 months ago

Cool! Yes, this is still wanted. Can you open a pull request with your current implementation @Hackzzila? Best to discuss with an implementation at hand.