client_rust
client_rust copied to clipboard
feat: derive register logic on struct of metrics
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.
- The metric name would be taken from the field name.
- The metric help text would be taken from the Rust doc String.
- The metric unit could be provided via a macro attribute.
#[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;
}
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!
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.