use std::error;
use std::fmt;
use std::io;
use crate::builder::MetricFormatter;
pub trait Metric {
fn as_metric_str(&self) -> &str;
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Counter {
repr: String,
}
impl Counter {
pub fn new(prefix: &str, key: &str, count: i64) -> Counter {
MetricFormatter::counter(prefix, key, count).build()
}
}
impl From<String> for Counter {
fn from(s: String) -> Self {
Counter { repr: s }
}
}
impl Metric for Counter {
fn as_metric_str(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Timer {
repr: String,
}
impl Timer {
pub fn new(prefix: &str, key: &str, time: u64) -> Timer {
MetricFormatter::timer(prefix, key, time).build()
}
}
impl From<String> for Timer {
fn from(s: String) -> Self {
Timer { repr: s }
}
}
impl Metric for Timer {
fn as_metric_str(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Gauge {
repr: String,
}
impl Gauge {
pub fn new(prefix: &str, key: &str, value: u64) -> Gauge {
MetricFormatter::gauge(prefix, key, value).build()
}
}
impl From<String> for Gauge {
fn from(s: String) -> Self {
Gauge { repr: s }
}
}
impl Metric for Gauge {
fn as_metric_str(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Meter {
repr: String,
}
impl Meter {
pub fn new(prefix: &str, key: &str, value: u64) -> Meter {
MetricFormatter::meter(prefix, key, value).build()
}
}
impl From<String> for Meter {
fn from(s: String) -> Self {
Meter { repr: s }
}
}
impl Metric for Meter {
fn as_metric_str(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Histogram {
repr: String,
}
impl Histogram {
pub fn new(prefix: &str, key: &str, value: u64) -> Histogram {
MetricFormatter::histogram(prefix, key, value).build()
}
}
impl From<String> for Histogram {
fn from(s: String) -> Self {
Histogram { repr: s }
}
}
impl Metric for Histogram {
fn as_metric_str(&self) -> &str {
&self.repr
}
}
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct Set {
repr: String,
}
impl Set {
pub fn new(prefix: &str, key: &str, value: i64) -> Set {
MetricFormatter::set(prefix, key, value).build()
}
}
impl From<String> for Set {
fn from(s: String) -> Self {
Set { repr: s }
}
}
impl Metric for Set {
fn as_metric_str(&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 source(&self) -> Option<&(dyn error::Error + 'static)> {
match self.repr {
ErrorRepr::IoError(ref err) => Some(err),
_ => None,
}
}
#[allow(deprecated, deprecated_in_future)]
fn description(&self) -> &str {
match self.repr {
ErrorRepr::IoError(ref err) => err.description(),
ErrorRepr::WithDescription(_, desc) => desc,
}
}
fn cause(&self) -> Option<&dyn error::Error> {
self.source()
}
}
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 {
#![allow(deprecated, deprecated_in_future)]
use super::{Counter, ErrorKind, Gauge, Histogram, Meter, Metric, MetricError, Set, Timer};
use std::error::Error;
use std::io;
#[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.as_metric_str());
}
#[test]
fn test_counter_no_prefix_to_metric_string() {
let counter = Counter::new("", "test.counter", 4);
assert_eq!("test.counter:4|c", counter.as_metric_str());
}
#[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.as_metric_str());
}
#[test]
fn test_timer_no_prefix_to_metric_string() {
let timer = Timer::new("", "test.timer", 34);
assert_eq!("test.timer:34|ms", timer.as_metric_str());
}
#[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.as_metric_str());
}
#[test]
fn test_gauge_no_prefix_to_metric_string() {
let gauge = Gauge::new("", "test.gauge", 2);
assert_eq!("test.gauge:2|g", gauge.as_metric_str());
}
#[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.as_metric_str());
}
#[test]
fn test_meter_no_prefix_to_metric_string() {
let meter = Meter::new("", "test.meter", 5);
assert_eq!("test.meter:5|m", meter.as_metric_str());
}
#[test]
fn test_histogram_to_metric_string() {
let histogram = Histogram::new("my.app.", "test.histogram", 45);
assert_eq!("my.app.test.histogram:45|h", histogram.as_metric_str());
}
#[test]
fn test_histogram_no_prefix_to_metric_string() {
let histogram = Histogram::new("", "test.histogram", 45);
assert_eq!("test.histogram:45|h", histogram.as_metric_str());
}
#[test]
fn test_set_to_metric_string() {
let set = Set::new("my.app.", "test.set", 4);
assert_eq!("my.app.test.set:4|s", set.as_metric_str());
}
#[test]
fn test_set_no_prefix_to_metric_string() {
let set = Set::new("", "test.set", 4);
assert_eq!("test.set:4|s", set.as_metric_str());
}
#[test]
fn test_metric_error_kind_io_error() {
let io_err = io::Error::new(io::ErrorKind::BrokenPipe, "Broken pipe");
let our_err = MetricError::from(io_err);
assert_eq!(ErrorKind::IoError, our_err.kind());
}
#[test]
fn test_metric_error_kind_invalid_input() {
let our_err = MetricError::from((ErrorKind::InvalidInput, "Nope"));
assert_eq!(ErrorKind::InvalidInput, our_err.kind());
}
#[test]
fn test_metric_error_description_io_error() {
let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "Permission!");
let our_err = MetricError::from(io_err);
assert_eq!("Permission!", our_err.description());
}
#[test]
fn test_metric_error_description_other() {
let our_err = MetricError::from((ErrorKind::InvalidInput, "Something!"));
assert_eq!("Something!", our_err.description());
}
#[test]
fn test_metric_error_cause_io_error() {
let io_err = io::Error::new(io::ErrorKind::TimedOut, "Timeout!");
let our_err = MetricError::from(io_err);
assert_eq!("Timeout!", our_err.source().unwrap().description());
}
#[test]
fn test_metric_error_cause_other() {
let our_err = MetricError::from((ErrorKind::InvalidInput, "Nope!"));
assert!(our_err.source().is_none());
}
}