use hdrhistogram::Histogram;
use super::latency_metrics_entry::time_stamp::seconds;
#[derive(Clone)]
pub struct LatencyMetricsEntrySession {
pub start_timestamp: u64,
pub latency: [Histogram<u64>; 2],
}
impl Default for LatencyMetricsEntrySession {
fn default() -> Self {
Self::new()
}
}
impl LatencyMetricsEntrySession {
pub const HISTOGRAM_LOWER_BOUND: u64 = 1;
pub const HISTOGRAM_UPPER_BOUND: u64 = seconds(100);
pub fn new() -> Self {
let hist = || {
Histogram::new_with_bounds(Self::HISTOGRAM_LOWER_BOUND, Self::HISTOGRAM_UPPER_BOUND, 2)
.expect("直方图边界为编译期常量,构造必成功")
};
Self {
start_timestamp: 0,
latency: [hist(), hist()],
}
}
pub fn return_to_pool(&mut self) {
self.latency[0].reset();
self.latency[1].reset();
}
#[inline]
pub fn start(&mut self, now_ticks: u64) {
self.start_timestamp = now_ticks;
}
#[inline]
pub fn record_value(&mut self, ver: usize, now_ticks: u64) {
if self.start_timestamp == 0 {
return;
}
let elapsed = now_ticks.saturating_sub(self.start_timestamp) as i64;
let value = if Self::is_valid_range(elapsed) {
elapsed as u64
} else {
Self::HISTOGRAM_UPPER_BOUND
};
let _ = self.latency[ver].record(value);
self.start_timestamp = 0;
}
#[inline]
pub fn record_elapsed(&mut self, ver: usize, elapsed: i64) {
if elapsed == 0 {
return;
}
let value = if Self::is_valid_range(elapsed) {
elapsed as u64
} else {
Self::HISTOGRAM_UPPER_BOUND
};
let _ = self.latency[ver].record(value);
}
#[inline]
pub fn is_valid_range(value: i64) -> bool {
value >= Self::HISTOGRAM_LOWER_BOUND as i64 && (value as u64) < Self::HISTOGRAM_UPPER_BOUND
}
}