posix4e / rust-metrics

Multi reporter metrics library (carbon, graphite, postgresql, prometheus)
Other
99 stars 19 forks source link

Derive Clone for Metric #53

Closed overvenus closed 8 years ago

waywardmonkeys commented 8 years ago

Where did you need to use clone on a Metric? I don't think this will do what you want in all cases, specifically for a Histogram.

overvenus commented 8 years ago

I use clone in register_metric!. Histogram seems to be a problem :confused:

use std::sync::Arc;

use metrics::registry::{Registry, StdRegistry};
use metrics::reporter::ConsoleReporter;

#[macro_export]
macro_rules! register_metric {
    ($(static ref $N:ident : $T:ty = $e:expr; $label:expr)*) => {
        $(
            lazy_static!(static ref $N : $T = $e;);
        )*

        use metrics;
        pub fn __metrics() -> Vec<(&'static str, metrics::metrics::Metric)> {
            let mut temp_vec = Vec::<(&'static str, metrics::metrics::Metric)>::new();
            $(
                // match *$N {
                //     metrics::metrics::Metric::Counter(ref c) => {
                //         temp_vec.push(($label, metrics::metrics::Metric::Counter(c.clone())))
                //     }
                //     metrics::metrics::Metric::Gauge(ref g) => {
                //         temp_vec.push(($label, metrics::metrics::Metric::Gauge(g.clone())))
                //     }
                //     metrics::metrics::Metric::Meter(ref m) => {
                //         temp_vec.push(($label, metrics::metrics::Metric::Meter(m.clone())))
                //     }
                //     metrics::metrics::Metric::Histogram(ref h) => {
                //         temp_vec.push(($label, metrics::metrics::Metric::Histogram(h.clone())))
                //     }
                // }
                temp_vec.push(($label, $N.clone()));
            )*
            temp_vec
        }
    };
}

lazy_static! {
    pub static ref REG: Arc<StdRegistry<'static>> = {
        use bar::__metrics;

        let mut r = StdRegistry::new();
        for (label, m) in __metrics() {
            r.insert(label, m);
        }
        Arc::new(r)
    };
}

pub fn init() {
    let arc_registry = (*REG).clone();
    let reporter = ConsoleReporter::new(arc_registry, "test");
    reporter.start(500);
}
use std::thread;
use std::time::Duration;

use metrics::metrics::{Metric, StdCounter};

register_metric! {
    static ref CTR_1: Metric = Metric::Counter(StdCounter::new()); "counter_1"
    static ref CTR_2: Metric = Metric::Counter(StdCounter::new()); "counter_2"
}

pub fn looop() {
    let c1 = if let Metric::Counter(ref c) = *CTR_1 {
        c.clone()
    } else {
        panic!()
    };

    let c2 = if let Metric::Counter(ref c) = *CTR_2 {
        c.clone()
    } else {
        panic!()
    };

    loop {
        thread::sleep(Duration::from_millis(500));
        c1.add(1);
        c2.add(2);
    }
}
posix4e commented 8 years ago

Can y'all help translate this in more detail?

overvenus commented 8 years ago

Oh, it's my bad.

bar.rs:

register_metric! {
    static ref CTR_1: Metric = Metric::Counter(StdCounter::new()); "counter_1"
}

It defines a static counter CTR_1 with a label counter_1, also it automatically generates a function named __metrics(), it returns a Vec of static metrics defined in register_metric!. We can use CTR_1 at any time.

foo.rs

lazy_static! {
    pub static ref REG: Arc<StdRegistry<'static>> = {
        // for mod bar
        {
            use bar::__metrics;

            let mut r = StdRegistry::new();
            for (label, m) in __metrics() {
                r.insert(label, m);
            }
        }
        // other mods
        {
            //....
        }
        Arc::new(r)
    };
}

It defines a static StdRegistry, all static metrics must be interted here.

pub fn init() {
    let arc_registry = (*REG).clone();
    let reporter = ConsoleReporter::new(arc_registry, "test");
    reporter.start(500);
}

Since I use lazy_static, all static variable will be evaluated at (*REG), so all metrics will be added to REG before starting reporter.

A buildable crate can be found at link

Back to topic

Why do I need clone?

If Metric did not support clone, register_metric! will end up with match Metric for every single metric.

BTW, how to expanded marcos?

cargo install cargo-expand
cargo expand
waywardmonkeys commented 8 years ago

I understand now. I will be home from a lot of travel tomorrow and will see if I can find a good solution for this.

overvenus commented 8 years ago

@waywardmonkeys Thank you!

I think this is the most convient way to use prometheus, just like prometheus in golang and java.

posix4e commented 8 years ago

Ganna hijack this commit as it's so small. I think it's justified. Ganna commit in 24 hours unless yo speakup @waywardmonkeys

waywardmonkeys commented 8 years ago

I'm going to merge this for now to unblock you, but I'm about to propose some API changes that will simplify a lot of things.