use histogram::Histogram;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
const ORDER_TYPE: Ordering = Ordering::Relaxed;
#[derive(Debug)]
pub struct MetricsError {
cause: &'static str,
}
impl From<&'static str> for MetricsError {
fn from(err: &'static str) -> MetricsError {
MetricsError { cause: err }
}
}
impl std::fmt::Display for MetricsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "metrics error: {}", self.cause)
}
}
#[derive(Default, Debug)]
pub struct Metrics {
errors_num: AtomicU64,
queries_num: AtomicU64,
errors_iter_num: AtomicU64,
queries_iter_num: AtomicU64,
retries_num: AtomicU64,
histogram: Arc<Mutex<Histogram>>,
}
impl Metrics {
pub fn new() -> Self {
Self {
errors_num: AtomicU64::new(0),
queries_num: AtomicU64::new(0),
errors_iter_num: AtomicU64::new(0),
queries_iter_num: AtomicU64::new(0),
retries_num: AtomicU64::new(0),
histogram: Arc::new(Mutex::new(Histogram::new())),
}
}
pub(crate) fn inc_failed_nonpaged_queries(&self) {
self.errors_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_total_nonpaged_queries(&self) {
self.queries_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_failed_paged_queries(&self) {
self.errors_iter_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_total_paged_queries(&self) {
self.queries_iter_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_retries_num(&self) {
self.retries_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn log_query_latency(&self, latency: u64) -> Result<(), MetricsError> {
let mut histogram_unlocked = self.histogram.lock().unwrap();
histogram_unlocked.increment(latency)?;
Ok(())
}
pub fn get_latency_avg_ms(&self) -> Result<u64, MetricsError> {
let histogram_unlocked = self.histogram.lock().unwrap();
Ok(histogram_unlocked.mean()?)
}
pub fn get_latency_percentile_ms(&self, percentile: f64) -> Result<u64, MetricsError> {
let histogram_unlocked = self.histogram.lock().unwrap();
Ok(histogram_unlocked.percentile(percentile)?)
}
pub fn get_errors_num(&self) -> u64 {
self.errors_num.load(ORDER_TYPE)
}
pub fn get_queries_num(&self) -> u64 {
self.queries_num.load(ORDER_TYPE)
}
pub fn get_errors_iter_num(&self) -> u64 {
self.errors_iter_num.load(ORDER_TYPE)
}
pub fn get_queries_iter_num(&self) -> u64 {
self.queries_iter_num.load(ORDER_TYPE)
}
pub fn get_retries_num(&self) -> u64 {
self.retries_num.load(ORDER_TYPE)
}
}