use std::error;
use std::fmt;
use std::io;
pub trait ToMetricString {
fn to_metric_string(&self) -> &str;
}
#[derive(PartialEq, Eq, Debug, Hash)]
pub struct Counter {
repr: String
}
impl Counter {
pub fn new(prefix: &str, key: &str, count: i64) -> Counter {
Counter{repr: format!("{}.{}:{}|c", prefix, key, count)}
}
}
impl ToMetricString for Counter {
fn to_metric_string(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash)]
pub struct Timer {
repr: String
}
impl Timer {
pub fn new(prefix: &str, key: &str, time: u64) -> Timer {
Timer{repr: format!("{}.{}:{}|ms", prefix, key, time)}
}
}
impl ToMetricString for Timer {
fn to_metric_string(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash)]
pub struct Gauge {
repr: String
}
impl Gauge {
pub fn new(prefix: &str, key: &str, value: u64) -> Gauge {
Gauge{repr: format!("{}.{}:{}|g", prefix, key, value)}
}
}
impl ToMetricString for Gauge {
fn to_metric_string(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash)]
pub struct Meter {
repr: String
}
impl Meter {
pub fn new(prefix: &str, key: &str, value: u64) -> Meter {
Meter{repr: format!("{}.{}:{}|m", prefix, key, value)}
}
}
impl ToMetricString for Meter {
fn to_metric_string(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
pub enum ErrorKind {
InvalidInput,
IoError,
}
#[derive(Debug)]
pub struct MetricError {
repr: ErrorRepr
}
#[derive(Debug)]
enum ErrorRepr {
WithDescription(ErrorKind, &'static str),
IoError(io::Error)
}
impl MetricError {
pub fn kind(&self) -> ErrorKind {
match self.repr {
ErrorRepr::IoError(_) => ErrorKind::IoError,
ErrorRepr::WithDescription(kind, _) => kind
}
}
}
impl fmt::Display for MetricError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.repr {
ErrorRepr::IoError(ref err) => err.fmt(f),
ErrorRepr::WithDescription(_, desc) => desc.fmt(f)
}
}
}
impl error::Error for MetricError {
fn description(&self) -> &str {
match self.repr {
ErrorRepr::IoError(ref err) => err.description(),
ErrorRepr::WithDescription(_, desc) => desc
}
}
fn cause(&self) -> Option<&error::Error> {
match self.repr {
ErrorRepr::IoError(ref err) => Some(err),
_ => None
}
}
}
impl From<io::Error> for MetricError {
fn from(err: io::Error) -> MetricError {
MetricError{repr: ErrorRepr::IoError(err)}
}
}
impl From<(ErrorKind, &'static str)> for MetricError {
fn from((kind, desc): (ErrorKind, &'static str)) -> MetricError {
MetricError{repr: ErrorRepr::WithDescription(kind, desc)}
}
}
pub type MetricResult<T> = Result<T, MetricError>;
#[cfg(test)]
mod tests {
use super::{
Counter,
Timer,
Gauge,
Meter,
ToMetricString
};
#[test]
fn test_counter_to_metric_string() {
let counter = Counter::new("my.app", "test.counter", 4);
assert_eq!("my.app.test.counter:4|c", counter.to_metric_string());
}
#[test]
fn test_timer_to_metric_string() {
let timer = Timer::new("my.app", "test.timer", 34);
assert_eq!("my.app.test.timer:34|ms", timer.to_metric_string());
}
#[test]
fn test_gauge_to_metric_string() {
let gauge = Gauge::new("my.app", "test.gauge", 2);
assert_eq!("my.app.test.gauge:2|g", gauge.to_metric_string());
}
#[test]
fn test_meter_to_metric_string() {
let meter = Meter::new("my.app", "test.meter", 5);
assert_eq!("my.app.test.meter:5|m", meter.to_metric_string());
}
}