tk_carbon/
public.rs

1use std::fmt::{self, Display};
2use std::io::Write;
3use std::sync::Arc;
4use std::time::{SystemTime, UNIX_EPOCH};
5
6use num_traits::Num;
7
8use element::{Metric};
9use channel::{channel, Sender};
10use {Init, Config};
11
12/// A structure that is used to submit values to carbon
13///
14/// Internally it uses a state machine to communicate to the underlying
15/// network connection(s)
16#[derive(Clone)]
17pub struct Carbon {
18    chan: Sender,
19}
20
21impl Carbon {
22    /// This creates an instance of the Carbon public interface and `Init`
23    /// structure that can be used to initialize a Proto instance
24    pub fn new(config: &Arc<Config>) -> (Carbon, Init) {
25        let (tx, rx) = channel(config.max_metrics_buffered);
26        return (
27            Carbon {
28                chan: tx,
29            },
30            Init {
31                chan: rx,
32                config: config.clone(),
33            }
34        )
35    }
36    /// Add any numeric value for carbon with current timestamp
37    ///
38    /// # Example
39    ///
40    /// ```ignore
41    /// carbon.add_value("my.metric", 1);
42    /// carbon.add_value(
43    ///     format_args!("metrics.{host}.cpu", host),
44    ///     27);
45    /// ```
46    ///
47    /// # Panics
48    ///
49    /// * When either name or value can't be formatted (Display'd)
50    /// * When formatted name contains a whitespace or a newline
51    pub fn add_value<N, V>(&self, name:N, value: V)
52        where N: Display, V: Num + Display
53    {
54        self.add_value_at(name, value, SystemTime::now());
55    }
56
57    /// Add any numeric value for carbon with specific timestamp
58    ///
59    /// # Example
60    ///
61    /// ```ignore
62    /// let timestamp = SystemTime::now();
63    /// carbon.add_value_at("my.metric", 1, timestamp);
64    /// carbon.add_value_at(
65    ///     format_args!("metrics.{host}.cpu", host),
66    ///     27, timestamp);
67    /// ```
68    ///
69    /// # Panics
70    ///
71    /// * When either name or value can't be formatted (Display'd)
72    /// * When formatted name contains a whitespace or a newline
73    /// * If timestamp is smaller than UNIX_EPOCH
74    pub fn add_value_at<N, V>(&self, name: N, value: V, ts: SystemTime)
75        where N: Display, V: Num + Display
76    {
77        let mut buf = Vec::with_capacity(100);
78        let tm = ts.duration_since(UNIX_EPOCH)
79            .expect("time is larger than epoch");
80        writeln!(&mut buf, "{} {} {}", name, value, tm.as_secs())
81            .expect("writing to buffer always succeed");
82        assert!(buf.iter()
83            .filter(|&&x| x == b' ' || x == b'\n' || x == b'\n')
84            .count() == 3, // exactly two spaces and a newline at the end
85            "Metric should not contain any spaces or newlines inside");
86        self.chan.send(Metric(buf));
87    }
88}
89
90impl fmt::Debug for Carbon {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        let (a, b) = self.chan.buffered();
93        write!(f, "Carbon({}/{})", a, b)
94    }
95}