autopush_common/
metrics.rs

1use std::net::UdpSocket;
2
3use cadence::{
4    BufferedUdpMetricSink, Counted, Counter, MetricBuilder, MetricError, MetricResult,
5    NopMetricSink, QueuingMetricSink, StatsdClient, StatsdClientBuilder,
6};
7
8use crate::metric_name::MetricName;
9
10/// Extension trait for StatsdClient to provide enum-based metric methods
11pub trait StatsdClientExt {
12    /// Increment a counter using a MetricName enum
13    fn incr(&self, metric: MetricName) -> MetricResult<Counter>;
14
15    /// Increment a counter using a raw string metric name
16    fn incr_raw(&self, metric: &str) -> MetricResult<Counter>;
17
18    /// Start a counter with tags using a MetricName enum
19    fn incr_with_tags(&self, metric: MetricName) -> MetricBuilder<'_, '_, Counter>;
20}
21
22impl StatsdClientExt for StatsdClient {
23    fn incr(&self, metric: MetricName) -> MetricResult<Counter> {
24        let metric_tag: &'static str = metric.into();
25        self.count(metric_tag, 1)
26    }
27
28    fn incr_raw(&self, metric: &str) -> MetricResult<Counter> {
29        self.count(metric, 1)
30    }
31
32    fn incr_with_tags(&self, metric: MetricName) -> MetricBuilder<'_, '_, Counter> {
33        let metric_tag: &'static str = metric.into();
34        self.count_with_tags(metric_tag, 1)
35    }
36}
37
38/// Create a cadence StatsdClientBuilder from the given options
39pub fn builder(
40    prefix: &str,
41    host: &Option<String>,
42    port: u16,
43) -> Result<StatsdClientBuilder, MetricError> {
44    let builder = if let Some(host) = host {
45        let socket = UdpSocket::bind("0.0.0.0:0")?;
46        socket.set_nonblocking(true)?;
47
48        let addr = (host.as_str(), port);
49        let udp_sink = BufferedUdpMetricSink::from(addr, socket)?;
50        let sink = QueuingMetricSink::from(udp_sink);
51        StatsdClient::builder(prefix, sink)
52    } else {
53        StatsdClient::builder(prefix, NopMetricSink)
54    };
55    Ok(builder.with_error_handler(|err| warn!("⚠️ Metric send error: {:?}", err)))
56}