use std::io;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
#[derive(Clone, Debug, Default)]
pub struct SinkStats {
pub bytes_sent: u64,
pub packets_sent: u64,
pub bytes_dropped: u64,
pub packets_dropped: u64,
}
#[derive(Debug, Clone, Default)]
pub struct SocketStats {
bytes_sent: Arc<AtomicU64>,
packets_sent: Arc<AtomicU64>,
bytes_dropped: Arc<AtomicU64>,
packets_dropped: Arc<AtomicU64>,
}
impl SocketStats {
pub fn incr_bytes_sent(&self, n: u64) {
self.bytes_sent.fetch_add(n, Ordering::Relaxed);
}
pub fn incr_packets_sent(&self) {
self.packets_sent.fetch_add(1, Ordering::Relaxed);
}
pub fn incr_bytes_dropped(&self, n: u64) {
self.bytes_dropped.fetch_add(n, Ordering::Relaxed);
}
pub fn incr_packets_dropped(&self) {
self.packets_dropped.fetch_add(1, Ordering::Relaxed);
}
pub fn update(&self, res: io::Result<usize>, len: usize) -> io::Result<usize> {
match res {
Ok(written) => {
self.incr_bytes_sent(written as u64);
self.incr_packets_sent();
Ok(written)
}
Err(e) => {
self.incr_bytes_dropped(len as u64);
self.incr_packets_dropped();
Err(e)
}
}
}
}
impl From<&SocketStats> for SinkStats {
fn from(stats: &SocketStats) -> Self {
SinkStats {
bytes_sent: stats.bytes_sent.load(Ordering::Relaxed),
packets_sent: stats.packets_sent.load(Ordering::Relaxed),
bytes_dropped: stats.bytes_dropped.load(Ordering::Relaxed),
packets_dropped: stats.packets_dropped.load(Ordering::Relaxed),
}
}
}
pub trait MetricSink {
fn emit(&self, metric: &str) -> io::Result<usize>;
fn flush(&self) -> io::Result<()> {
Ok(())
}
fn stats(&self) -> SinkStats {
SinkStats::default()
}
}
#[derive(Debug, Clone)]
pub struct NopMetricSink;
impl MetricSink for NopMetricSink {
fn emit(&self, _metric: &str) -> io::Result<usize> {
Ok(0)
}
}
#[cfg(test)]
mod tests {
use super::{MetricSink, NopMetricSink};
#[test]
fn test_nop_metric_sink() {
let sink = NopMetricSink;
assert_eq!(0, sink.emit("baz:4|c").unwrap());
}
}