1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
extern crate hostname; extern crate rand; use hostname::get_hostname; use rand::prelude::*; use std::net::*; use std::sync::mpsc::*; use std::thread; #[derive(Clone)] pub struct Vapor { hostname: String, sender: Sender<Vec<u8>>, } impl Vapor { pub fn new(host_name: &str, port: u16) -> Vapor { let address = format!("{}:{}", host_name, port); let (tx, rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel(); thread::spawn(move || { let mut socket = None; loop { match rx.recv() { Ok(data) => { if socket.is_none() { socket = UdpSocket::bind("0.0.0.0:0").ok(); } if let Some(s) = &socket { match s.send_to(data.as_slice(), &address) { Ok(_) => {}, Err(_) => {} } } }, Err(err) => { eprintln!("vapor thread crashed: {:?}", err); } } } }); Vapor { hostname: get_hostname().unwrap_or_else(|| "unknown".to_string()), sender: tx, } } pub fn event<S: AsRef<str>>(&self, name: S, count: i64, period: u16) { let data = format!("e/{}/{}/{}", self.calc_name(name), count, period); let _ = self.sender.send(data.into_bytes()); } pub fn gauge<S: AsRef<str>>(&self, name: S, value: i64) { let data = format!("g/{}/{}", self.calc_name(name), value); let _ = self.sender.send(data.into_bytes()); } pub fn sample_event<S: AsRef<str>>(&self, name: S, count: i64, period: u16, sample_rate: f64) { if Vapor::should_send(sample_rate) { self.event(name, count, period); } } pub fn sample_gauge<S: AsRef<str>>(&self, name: S, value: i64, sample_rate: f64) { if Vapor::should_send(sample_rate) { self.gauge(name, value); } } fn calc_name<S: AsRef<str>>(&self, name: S) -> String { name.as_ref() .replace("%h", &self.hostname) .replace("/", "") } fn should_send(sample_rate: f64) -> bool { let mut rng = thread_rng(); let value: f64 = rng.gen(); value < sample_rate } }