Struct cadence::StatsdClient

source ·
pub struct StatsdClient { /* private fields */ }
Expand description

Client for Statsd that implements various traits to record metrics.

§Traits

The client is the main entry point for users of this library. It supports several traits for recording metrics of different types.

  • Counted for emitting counters.
  • Timed for emitting timings.
  • Gauged for emitting gauge values.
  • Metered for emitting meter values.
  • Histogrammed for emitting histogram values.
  • Distributed for emitting distribution values.
  • Setted for emitting set values.
  • MetricClient for a combination of all of the above.

For more information about the uses for each type of metric, see the documentation for each mentioned trait.

§Sinks

The client uses some implementation of a MetricSink to emit the metrics.

In simple use cases when performance isn’t critical, the UdpMetricSink is an acceptable choice since it is the simplest to use and understand.

When performance is more important, users will want to use the BufferedUdpMetricSink in combination with the QueuingMetricSink for maximum isolation between the sending of metrics and your application as well as minimum overhead when sending metrics.

§Threading

The StatsdClient is designed to work in a multithreaded application. All parts of the client can be shared between threads (i.e. it is Send and Sync). An example of how to use the client in a multithreaded environment is given below.

In the following example, we create a struct MyRequestHandler that has a single method that spawns a thread to do some work and emit a metric.

§Wrapping With An Arc

In order to share a client between multiple threads, you’ll need to wrap it with an atomic reference counting pointer (std::sync::Arc). You should refer to the client by the trait of all its methods for recording metrics (MetricClient) as well as the Send and Sync traits since the idea is to share this between threads.

use std::panic::RefUnwindSafe;
use std::net::UdpSocket;
use std::sync::Arc;
use std::thread;
use cadence::prelude::*;
use cadence::{StatsdClient, BufferedUdpMetricSink, DEFAULT_PORT};

struct MyRequestHandler {
    metrics: Arc<dyn MetricClient + Send + Sync + RefUnwindSafe>,
}

impl MyRequestHandler {
    fn new() -> MyRequestHandler {
        let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
        let host = ("localhost", DEFAULT_PORT);
        let sink = BufferedUdpMetricSink::from(host, socket).unwrap();
        MyRequestHandler {
            metrics: Arc::new(StatsdClient::from_sink("some.prefix", sink))
        }
    }

    fn handle_some_request(&self) -> Result<(), String> {
        let metric_ref = self.metrics.clone();
        let _t = thread::spawn(move || {
            println!("Hello from the thread!");
            metric_ref.count("request.handler", 1);
        });

        Ok(())
    }
}

Implementations§

source§

impl StatsdClient

source

pub fn from_sink<T>(prefix: &str, sink: T) -> Self
where T: MetricSink + Sync + Send + RefUnwindSafe + 'static,

Create a new client instance that will use the given prefix for all metrics emitted to the given MetricSink implementation.

Note that this client will discard errors encountered when sending metrics via the MetricBuilder::send() method.

§No-op Example
use cadence::{StatsdClient, NopMetricSink};

let prefix = "my.stats";
let client = StatsdClient::from_sink(prefix, NopMetricSink);
§UDP Socket Example
use std::net::UdpSocket;
use cadence::{StatsdClient, UdpMetricSink, DEFAULT_PORT};

let prefix = "my.stats";
let host = ("127.0.0.1", DEFAULT_PORT);

let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
socket.set_nonblocking(true).unwrap();

let sink = UdpMetricSink::from(host, socket).unwrap();
let client = StatsdClient::from_sink(prefix, sink);
§Buffered UDP Socket Example
use std::net::UdpSocket;
use cadence::{StatsdClient, BufferedUdpMetricSink, DEFAULT_PORT};

let prefix = "my.stats";
let host = ("127.0.0.1", DEFAULT_PORT);

let socket = UdpSocket::bind("0.0.0.0:0").unwrap();

let sink = BufferedUdpMetricSink::from(host, socket).unwrap();
let client = StatsdClient::from_sink(prefix, sink);
Examples found in repository?
examples/arc-wrapped-client.rs (line 30)
28
29
30
31
32
    fn new() -> ThreadedHandler {
        ThreadedHandler {
            metrics: Arc::new(StatsdClient::from_sink("example.prefix", NopMetricSink)),
        }
    }
More examples
Hide additional examples
examples/custom-value-type.rs (line 37)
35
36
37
38
39
40
41
42
fn main() {
    let sink = NopMetricSink;
    let client = StatsdClient::from_sink("example.prefix", sink);

    client.gauge("user.happiness", UserHappiness::VeryHappy).unwrap();
    client.gauge("user.happiness", UserHappiness::KindaHappy).unwrap();
    client.gauge("user.happiness", UserHappiness::Sad).unwrap();
}
examples/nop-sink.rs (line 20)
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {
    let sink = NopMetricSink;
    let client = StatsdClient::from_sink("example.prefix", sink);

    client.count("example.counter", 1).unwrap();
    client.gauge("example.gauge", 5).unwrap();
    client.gauge("example.gauge", 5.0).unwrap();
    client.time("example.timer", 32).unwrap();
    client.time("example.timer", Duration::from_millis(32)).unwrap();
    client.histogram("example.histogram", 22).unwrap();
    client.histogram("example.histogram", Duration::from_nanos(22)).unwrap();
    client.histogram("example.histogram", 22.0).unwrap();
    client.distribution("example.distribution", 33).unwrap();
    client.distribution("example.distribution", 33.0).unwrap();
    client.meter("example.meter", 8).unwrap();
    client.set("example.set", 44).unwrap();
}
examples/simple-sink.rs (line 22)
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
fn main() {
    let sock = UdpSocket::bind("0.0.0.0:0").unwrap();
    let sink = UdpMetricSink::from(("localhost", DEFAULT_PORT), sock).unwrap();
    let client = StatsdClient::from_sink("example.prefix", sink);

    client.count("example.counter", 1).unwrap();
    client.gauge("example.gauge", 5).unwrap();
    client.gauge("example.gauge", 5.0).unwrap();
    client.time("example.timer", 32).unwrap();
    client.time("example.timer", Duration::from_millis(32)).unwrap();
    client.histogram("example.histogram", 22).unwrap();
    client.histogram("example.histogram", Duration::from_nanos(22)).unwrap();
    client.histogram("example.histogram", 22.0).unwrap();
    client.distribution("example.distribution", 33).unwrap();
    client.distribution("example.distribution", 33.0).unwrap();
    client.meter("example.meter", 8).unwrap();
    client.set("example.set", 44).unwrap();
}
examples/wrapped.rs (line 54)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() {
    let real_sink = NopMetricSink;
    let reference1 = CloneableSink::new(real_sink);
    let reference2 = reference1.clone();
    let client = StatsdClient::from_sink("prefix", reference1);

    let _ = reference2.flush();

    client.count("example.counter", 1).unwrap();
    client.gauge("example.gauge", 5).unwrap();
    client.gauge("example.gauge", 5.0).unwrap();
    client.time("example.timer", 32).unwrap();
    client.time("example.timer", Duration::from_millis(32)).unwrap();
    client.histogram("example.histogram", 22).unwrap();
    client.histogram("example.histogram", Duration::from_nanos(22)).unwrap();
    client.histogram("example.histogram", 22.0).unwrap();
    client.distribution("example.distribution", 33).unwrap();
    client.distribution("example.distribution", 33.0).unwrap();
    client.meter("example.meter", 8).unwrap();
    client.set("example.set", 44).unwrap();

    let _ = reference2.flush();
}
examples/production-sink.rs (line 24)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
fn main() {
    let sock = UdpSocket::bind("0.0.0.0:0").unwrap();
    let buffered = BufferedUdpMetricSink::from(("localhost", DEFAULT_PORT), sock).unwrap();
    let queued = QueuingMetricSink::from(buffered);
    let client = StatsdClient::from_sink("example.prefix", queued);

    client.count("example.counter", 1).unwrap();
    client.gauge("example.gauge", 5).unwrap();
    client.gauge("example.gauge", 5.0).unwrap();
    client.time("example.timer", 32).unwrap();
    client.time("example.timer", Duration::from_millis(32)).unwrap();
    client.histogram("example.histogram", 22).unwrap();
    client.histogram("example.histogram", Duration::from_nanos(22)).unwrap();
    client.histogram("example.histogram", 22.0).unwrap();
    client.distribution("example.distribution", 33).unwrap();
    client.distribution("example.distribution", 33.0).unwrap();
    client.meter("example.meter", 8).unwrap();
    client.set("example.set", 44).unwrap();
}
source

pub fn builder<T>(prefix: &str, sink: T) -> StatsdClientBuilder
where T: MetricSink + Sync + Send + RefUnwindSafe + 'static,

Create a new builder with the provided prefix and metric sink.

A prefix and a metric sink are required to create a new client instance. All other optional customizations can be set by calling methods on the returned builder. Any customizations that aren’t set by the caller will use defaults.

Note, though a metric prefix is required, you may pass an empty string as a prefix. In this case, the metrics emitted will use only the bare keys supplied when you call the various methods to emit metrics.

General defaults:

  • A no-op error handler will be used by default. Note that this only affects errors encountered when using the MetricBuilder::send() method (as opposed to .try_send() or any other method for sending metrics).
§Example
use cadence::prelude::*;
use cadence::{StatsdClient, MetricError, NopMetricSink};

fn my_handler(err: MetricError) {
    println!("Metric error: {}", err);
}

let client = StatsdClient::builder("some.prefix", NopMetricSink)
    .with_error_handler(my_handler)
    .build();

client.gauge_with_tags("some.key", 7)
   .with_tag("region", "us-west-1")
   .send();
Examples found in repository?
examples/value-packing.rs (line 22)
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn main() {
    fn my_error_handler(err: MetricError) {
        eprintln!("Error sending metrics: {}", err);
    }

    let client = StatsdClient::builder("my.prefix", NopMetricSink)
        .with_error_handler(my_error_handler)
        .build();

    // In this case we are sending a distribution metric with two tag key-value
    // pairs. If sending the metric fails, our error handler set above will
    // be invoked to do something with the metric error.
    client
        .distribution_with_tags("latency.milliseconds", vec![10, 20, 30, 40, 50])
        .with_tag("app", "search")
        .with_tag("region", "us-west-2")
        .send();

    // In this case we are sending the same distribution metrics with two tags.
    // The results of sending the metric (or failing to send it) are returned
    // to the caller to do something with.
    let res = client
        .distribution_with_tags("latency.milliseconds", vec![10, 20, 30, 40, 50])
        .with_tag("app", "search")
        .with_tag("region", "us-west-2")
        .try_send();

    println!("Result of metric send: {:?}", res);
}
More examples
Hide additional examples
examples/sending-tags.rs (line 25)
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn main() {
    fn my_error_handler(err: MetricError) {
        eprintln!("Error sending metrics: {}", err);
    }

    // Create a client with an error handler and default "region" tag
    let client = StatsdClient::builder("my.prefix", NopMetricSink)
        .with_error_handler(my_error_handler)
        .with_tag("region", "us-west-2")
        .build();

    // In this case we are sending a counter metric with two tag key-value
    // pairs. If sending the metric fails, our error handler set above will
    // be invoked to do something with the metric error.
    client
        .count_with_tags("requests.handled", 1)
        .with_tag("app", "search")
        .with_tag("user", "1234")
        .send();

    // In this case we are sending the same counter metrics with two tags.
    // The results of sending the metric (or failing to send it) are returned
    // to the caller to do something with.
    let res = client
        .count_with_tags("requests.handled", 1)
        .with_tag("app", "search")
        .with_tag("user", "1234")
        .try_send();

    println!("Result of metric send: {:?}", res);
}
source

pub fn flush(&self) -> MetricResult<()>

Flush the underlying metric sink.

This is helpful for when you’d like to buffer metrics but still want strong control over when to emit them. For example, you are using a BufferedUdpMetricSink and have just emitted some time-sensitive metrics, but you aren’t sure if the buffer is full or not. Thus, you can use flush to force the sink to flush your metrics now.

§Buffered UDP Socket Example
use std::net::UdpSocket;
use cadence::prelude::*;
use cadence::{StatsdClient, BufferedUdpMetricSink, DEFAULT_PORT};

let prefix = "my.stats";
let host = ("127.0.0.1", DEFAULT_PORT);

let socket = UdpSocket::bind("0.0.0.0:0").unwrap();

let sink = BufferedUdpMetricSink::from(host, socket).unwrap();
let client = StatsdClient::from_sink(prefix, sink);

client.count("time-sensitive.keyA", 1);
client.count("time-sensitive.keyB", 2);
client.count("time-sensitive.keyC", 3);
// Any number of time-sensitive metrics ...
client.flush();

Trait Implementations§

source§

impl<T> Counted<T> for StatsdClient
where T: ToCounterValue,

source§

fn count_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Counter>

Increment or decrement the counter by the given amount and return a MetricBuilder that can be used to add tags to the metric.
source§

fn count(&self, key: &str, count: T) -> MetricResult<Counter>

Increment or decrement the counter by the given amount
source§

impl CountedExt for StatsdClient

source§

fn incr(&self, key: &str) -> MetricResult<Counter>

Increment the counter by 1
source§

fn incr_with_tags<'a>(&'a self, key: &'a str) -> MetricBuilder<'_, '_, Counter>

Increment the counter by 1 and return a MetricBuilder that can be used to add tags to the metric.
source§

fn decr(&self, key: &str) -> MetricResult<Counter>

Decrement the counter by 1
source§

fn decr_with_tags<'a>(&'a self, key: &'a str) -> MetricBuilder<'_, '_, Counter>

Decrement the counter by 1 and return a MetricBuilder that can be used to add tags to the metric.
source§

impl Debug for StatsdClient

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Distributed<T> for StatsdClient

source§

fn distribution_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Distribution>

Record a single distribution value with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn distribution(&self, key: &str, value: T) -> MetricResult<Distribution>

Record a single distribution value with the given key
source§

impl<T> Gauged<T> for StatsdClient
where T: ToGaugeValue,

source§

fn gauge_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Gauge>

Record a gauge value with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn gauge(&self, key: &str, value: T) -> MetricResult<Gauge>

Record a gauge value with the given key
source§

impl<T> Histogrammed<T> for StatsdClient

source§

fn histogram_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Histogram>

Record a single histogram value with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn histogram(&self, key: &str, value: T) -> MetricResult<Histogram>

Record a single histogram value with the given key
source§

impl<T> Metered<T> for StatsdClient
where T: ToMeterValue,

source§

fn meter_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Meter>

Record a meter value with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn meter(&self, key: &str, value: T) -> MetricResult<Meter>

Record a meter value with the given key
source§

impl MetricBackend for StatsdClient

source§

fn send_metric<M>(&self, metric: &M) -> MetricResult<()>
where M: Metric,

Send a full formed Metric implementation via the underlying MetricSink Read more
source§

fn consume_error(&self, err: MetricError)

Consume a possible error from attempting to send a metric. Read more
source§

impl<T> Setted<T> for StatsdClient
where T: ToSetValue,

source§

fn set_with_tags<'a>( &'a self, key: &'a str, value: T ) -> MetricBuilder<'_, '_, Set>

Record a single set value with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn set(&self, key: &str, value: T) -> MetricResult<Set>

Record a single set value with the given key
source§

impl<T> Timed<T> for StatsdClient
where T: ToTimerValue,

source§

fn time_with_tags<'a>( &'a self, key: &'a str, time: T ) -> MetricBuilder<'_, '_, Timer>

Record a timing in milliseconds with the given key and return a MetricBuilder that can be used to add tags to the metric.
source§

fn time(&self, key: &str, time: T) -> MetricResult<Timer>

Record a timing in milliseconds with the given key
source§

impl MetricClient for StatsdClient

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.