use cadence::{SpyMetricSink, StatsdClient}; use cadence_macros::{ statsd_count, statsd_distribution, statsd_gauge, statsd_histogram, statsd_meter, statsd_set, statsd_time, SingletonHolder, }; use crossbeam_channel::Receiver; use std::collections::HashSet; use std::time::Duration; static RX: SingletonHolder>> = SingletonHolder::new(); /// Set a default client and save a reference to a channel for inspecting metrics fn init_default_client() { // Save a global reference to the receiver that the spy sink will make any // written metrics available in. let (rx, sink) = SpyMetricSink::new(); RX.set(rx); cadence_macros::set_global_default(StatsdClient::from_sink("my.prefix", sink)); } /// Get the all strings written to the sink so far. fn read_all_metrics() -> HashSet { let rx = RX.get().unwrap(); // We use a SpyMetricSink above (non-buffered) for the global client so each metric // is a separate string that we can read from the channel and look for in our tests. let mut out = HashSet::new(); while let Ok(v) = rx.try_recv() { out.insert(String::from_utf8(v).unwrap()); } out } #[test] fn test_macros() { // NOTE: We're testing all the macros as part of a single #[test] block // because test functions are run in multiple threads by default and we // wouldn't be able to guarantee which metrics were in the rx buffer when // the test ran otherwise. init_default_client(); fn test_counter_macros() { statsd_count!("some.counter", 123); statsd_count!("some.counter", 123, "host" => "web01.example.com", "slice" => "a"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.counter:123|c".to_owned())); assert!(metrics.contains(&"my.prefix.some.counter:123|c|#host:web01.example.com,slice:a".to_owned())); } fn test_timer_macros() { statsd_time!("some.timer", 334); statsd_time!("some.timer", 334, "type" => "api", "status" => "200"); statsd_time!("some.timer", Duration::from_millis(334), "type" => "web"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.timer:334|ms".to_owned())); assert!(metrics.contains(&"my.prefix.some.timer:334|ms|#type:api,status:200".to_owned())); assert!(metrics.contains(&"my.prefix.some.timer:334|ms|#type:web".to_owned())); } fn test_gauge_macros() { statsd_gauge!("some.gauge", 42); statsd_gauge!("some.gauge", 42, "org" => "123", "service" => "gateway"); statsd_gauge!("some.gauge", 35.4, "org" => "456"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.gauge:42|g".to_owned())); assert!(metrics.contains(&"my.prefix.some.gauge:42|g|#org:123,service:gateway".to_owned())); assert!(metrics.contains(&"my.prefix.some.gauge:35.4|g|#org:456".to_owned())); } fn test_meter_macros() { statsd_meter!("some.meter", 1); statsd_meter!("some.meter", 1, "foo" => "bar", "result" => "reject"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.meter:1|m".to_owned())); assert!(metrics.contains(&"my.prefix.some.meter:1|m|#foo:bar,result:reject".to_owned())); } fn test_histogram_macros() { statsd_histogram!("some.histogram", 223); statsd_histogram!("some.histogram", 223, "method" => "auth", "result" => "error"); statsd_histogram!("some.histogram", Duration::from_nanos(223), "method" => "list"); statsd_histogram!("some.histogram", 22.3, "method" => "list"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.histogram:223|h".to_owned())); assert!(metrics.contains(&"my.prefix.some.histogram:223|h|#method:auth,result:error".to_owned())); assert!(metrics.contains(&"my.prefix.some.histogram:223|h|#method:list".to_owned())); assert!(metrics.contains(&"my.prefix.some.histogram:22.3|h|#method:list".to_owned())); } fn test_distribution_macros() { statsd_distribution!("some.distribution", 22); statsd_distribution!("some.distribution", 22, "method" => "auth", "result" => "error"); statsd_distribution!("some.distribution", 2.21, "method" => "list"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.distribution:22|d".to_owned())); assert!(metrics.contains(&"my.prefix.some.distribution:22|d|#method:auth,result:error".to_owned())); assert!(metrics.contains(&"my.prefix.some.distribution:2.21|d|#method:list".to_owned())); } fn test_set_macros() { statsd_set!("some.set", 348); statsd_set!("some.set", 348, "service" => "user", "host" => "app01.example.com"); let metrics = read_all_metrics(); assert!(metrics.contains(&"my.prefix.some.set:348|s".to_owned())); assert!(metrics.contains(&"my.prefix.some.set:348|s|#service:user,host:app01.example.com".to_owned())); } test_counter_macros(); test_timer_macros(); test_gauge_macros(); test_meter_macros(); test_histogram_macros(); test_distribution_macros(); test_set_macros(); }