use std::time::Duration;
use super::{
CounterHandle, GaugeHandle, HistogramHandle, HistogramValue, MetricRegistrationError,
MetricsRegistry,
};
const ACTIVE_COUNT_NAME: &str = "conversation_active_count";
const COMPLETION_COUNT_NAME: &str = "conversation_completion_count";
const DURATION_NAME: &str = "conversation_duration";
const ERROR_COUNT_NAME: &str = "conversation_error_count";
#[derive(Clone, Debug)]
pub struct ConversationMetrics {
pub active_count: GaugeHandle,
pub completion_count: CounterHandle,
pub duration: HistogramHandle,
pub error_count: CounterHandle,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConversationOutcome {
Completed,
Failed,
TimedOut,
}
impl ConversationMetrics {
pub fn new<Bucket>(
registry: &MetricsRegistry,
duration_buckets: Vec<Bucket>,
) -> Result<Self, MetricRegistrationError>
where
Bucket: HistogramValue,
{
let active_count =
registry.register_gauge(ACTIVE_COUNT_NAME, std::iter::empty::<(&str, &str)>())?;
let completion_count =
registry.register_counter(COMPLETION_COUNT_NAME, std::iter::empty::<(&str, &str)>())?;
let duration = registry.register_histogram(
DURATION_NAME,
std::iter::empty::<(&str, &str)>(),
duration_buckets,
)?;
let error_count =
registry.register_counter(ERROR_COUNT_NAME, std::iter::empty::<(&str, &str)>())?;
Ok(Self {
active_count,
completion_count,
duration,
error_count,
})
}
pub fn record_start(&self) {
self.active_count.increment();
}
pub fn record_end(&self) {
self.active_count.decrement();
}
pub fn record_completion(&self) {
self.completion_count.increment();
}
pub fn record_duration(&self, duration: Duration) {
self.duration.observe(duration.as_secs_f64());
}
pub fn record_error(&self) {
self.error_count.increment();
}
pub fn record_terminal(&self, outcome: ConversationOutcome, duration: Duration) {
match outcome {
ConversationOutcome::Completed => self.record_completion(),
ConversationOutcome::Failed | ConversationOutcome::TimedOut => self.record_error(),
}
self.record_duration(duration);
self.record_end();
}
}