use crate::core::Atomic;
use crate::counter::{CounterWithValueType, GenericLocalCounter};
use crate::histogram::{Instant, LocalHistogram};
use crate::metrics::MayFlush;
use crate::timer;
use parking_lot::Mutex;
use std::thread::LocalKey;
pub trait CounterDelegator<T: 'static + MayFlush, V: CounterWithValueType> {
fn get_root_metric(&self) -> &'static LocalKey<T>;
fn get_local<'a>(&self, root_metric: &'a T) -> &'a GenericLocalCounter<V::ValueType>;
}
pub trait HistogramDelegator<T: 'static + MayFlush> {
fn get_root_metric(&self) -> &'static LocalKey<T>;
fn get_local<'a>(&self, root_metric: &'a T) -> &'a LocalHistogram;
}
#[derive(Debug)]
pub struct AFLocalCounter<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
{
delegator: D,
_p: std::marker::PhantomData<(Mutex<T>, Mutex<V>)>,
}
impl<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
AFLocalCounter<T, V, D>
{
pub fn new(delegator: D) -> AFLocalCounter<T, V, D> {
timer::ensure_updater();
AFLocalCounter {
delegator,
_p: std::marker::PhantomData,
}
}
}
impl<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
AFLocalCounter<T, V, D>
{
#[inline]
fn get_root_metric(&self) -> &'static LocalKey<T> {
self.delegator.get_root_metric()
}
#[inline]
fn get_counter<'a>(&self, root_metric: &'a T) -> &'a GenericLocalCounter<V::ValueType> {
self.delegator.get_local(root_metric)
}
#[inline]
pub fn inc_by(&self, v: <V::ValueType as Atomic>::T) {
self.get_root_metric().with(|m| {
let counter = self.get_counter(m);
counter.inc_by(v);
m.may_flush();
})
}
#[inline]
pub fn inc(&self) {
self.get_root_metric().with(|m| {
let counter = self.get_counter(m);
counter.inc();
m.may_flush();
})
}
#[inline]
pub fn get(&self) -> <V::ValueType as Atomic>::T {
self.get_root_metric().with(|m| {
let counter = self.get_counter(m);
counter.get()
})
}
#[inline]
pub fn reset(&self) {
self.get_root_metric().with(|m| {
let counter = self.get_counter(m);
counter.reset();
})
}
#[inline]
pub fn flush(&self) {
self.get_root_metric().with(|m| m.flush())
}
}
#[derive(Debug)]
pub struct AFLocalHistogram<T: 'static + MayFlush, D: HistogramDelegator<T>> {
delegator: D,
_p: std::marker::PhantomData<Mutex<T>>,
}
impl<T: 'static + MayFlush, D: HistogramDelegator<T>> AFLocalHistogram<T, D> {
pub fn new(delegator: D) -> AFLocalHistogram<T, D> {
timer::ensure_updater();
AFLocalHistogram {
delegator,
_p: std::marker::PhantomData,
}
}
}
impl<M: 'static + MayFlush, D: HistogramDelegator<M>> AFLocalHistogram<M, D> {
pub fn observe(&self, v: f64) {
self.delegator.get_root_metric().with(|m| {
let local = self.delegator.get_local(m);
local.observe(v);
m.may_flush();
})
}
pub fn observe_closure_duration<F, T>(&self, f: F) -> T
where
F: FnOnce() -> T,
{
let instant = Instant::now();
let res = f();
let elapsed = instant.elapsed_sec();
self.observe(elapsed);
res
}
#[cfg(feature = "nightly")]
pub fn observe_closure_duration_coarse<F, T>(&self, f: F) -> T
where
F: FnOnce() -> T,
{
let instant = Instant::now_coarse();
let res = f();
let elapsed = instant.elapsed_sec();
self.observe(elapsed);
res
}
pub fn clear(&self) {
self.delegator
.get_root_metric()
.with(|m| self.delegator.get_local(m).clear())
}
pub fn flush(&self) {
self.delegator
.get_root_metric()
.with(|m| self.delegator.get_local(m).flush());
}
pub fn get_sample_sum(&self) -> f64 {
self.delegator
.get_root_metric()
.with(|m| self.delegator.get_local(m).get_sample_sum())
}
pub fn get_sample_count(&self) -> u64 {
self.delegator
.get_root_metric()
.with(|m| self.delegator.get_local(m).get_sample_count())
}
}