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}