use std::sync::Arc;
use std::time::Duration;
#[derive(Debug, Clone, Copy, Default)]
pub struct ConnectionPoolStats {
pub active_connections: u32,
pub idle_connections: u32,
pub total_connections_created: u64,
pub connections_closed: u64,
}
pub trait Metrics: Send + Sync + 'static {
fn on_request(&self, _method: &str) {}
fn on_response(&self, _method: &str) {}
fn on_error(&self, _method: &str, _error_kind: &str) {}
fn on_latency(&self, _method: &str, _duration: Duration) {}
fn on_queue_depth_change(&self, _active_queues: usize) {}
fn on_connection_pool_stats(&self, _stats: &ConnectionPoolStats) {}
fn on_persistence_error(&self, _operation: &str, _error_kind: &str) {}
fn on_push_delivery(&self, _outcome: &str) {}
fn on_rpc_call(&self, _call: &RpcCall<'_>) {}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct RpcCall<'a> {
pub system: &'a str,
pub method: Option<&'a str>,
pub duration: Duration,
pub status_code: Option<&'a str>,
pub error_type: Option<&'a str>,
}
pub mod persistence_operation {
pub const STATUS_UPDATE: &str = "status_update";
pub const ARTIFACT_APPEND: &str = "artifact_append";
pub const ARTIFACT_PUSH: &str = "artifact_push";
pub const EVENT_APPEND: &str = "event_append";
pub const TASK_SNAPSHOT: &str = "task_snapshot";
pub const FAILED_STATE: &str = "failed_state";
pub const HISTORY_APPEND: &str = "history_append";
pub const EVENT_LOG_CATCHUP: &str = "event_log_catchup";
pub const QUEUE_HANDOFF: &str = "queue_handoff";
}
pub mod event_log_catchup_error {
pub const TIMED_OUT: &str = "timed_out";
}
pub mod event_append_error {
pub const POSITION_CONFLICT: &str = "position_conflict";
pub const TASK_ABSENT: &str = "task_absent";
}
pub mod queue_handoff_error {
pub const CHANNEL_CLOSED: &str = "channel_closed";
}
pub mod push_outcome {
pub const DELIVERED: &str = "delivered";
pub const FAILED: &str = "failed";
pub const TIMEOUT: &str = "timeout";
pub const TIMEOUT_TRUNCATED: &str = "timeout_truncated";
pub const SKIPPED: &str = "skipped";
}
#[derive(Debug, Default)]
pub struct NoopMetrics;
impl Metrics for NoopMetrics {}
#[derive(Clone)]
pub struct MetricsHandle(Arc<dyn Metrics>);
impl MetricsHandle {
#[must_use]
pub fn new<M: Metrics>(metrics: M) -> Self {
Self(Arc::new(metrics))
}
#[must_use]
pub fn from_arc(metrics: Arc<dyn Metrics>) -> Self {
Self(metrics)
}
}
impl Default for MetricsHandle {
fn default() -> Self {
Self(Arc::new(NoopMetrics))
}
}
impl std::fmt::Debug for MetricsHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("MetricsHandle(..)")
}
}
impl std::ops::Deref for MetricsHandle {
type Target = dyn Metrics;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl<M: Metrics> From<Arc<M>> for MetricsHandle {
fn from(metrics: Arc<M>) -> Self {
Self(metrics)
}
}
impl<T: Metrics + ?Sized> Metrics for Arc<T> {
fn on_request(&self, method: &str) {
(**self).on_request(method);
}
fn on_response(&self, method: &str) {
(**self).on_response(method);
}
fn on_error(&self, method: &str, error: &str) {
(**self).on_error(method, error);
}
fn on_latency(&self, method: &str, duration: Duration) {
(**self).on_latency(method, duration);
}
fn on_queue_depth_change(&self, active_queues: usize) {
(**self).on_queue_depth_change(active_queues);
}
fn on_connection_pool_stats(&self, stats: &ConnectionPoolStats) {
(**self).on_connection_pool_stats(stats);
}
fn on_persistence_error(&self, operation: &str, error_kind: &str) {
(**self).on_persistence_error(operation, error_kind);
}
fn on_push_delivery(&self, outcome: &str) {
(**self).on_push_delivery(outcome);
}
fn on_rpc_call(&self, call: &RpcCall<'_>) {
(**self).on_rpc_call(call);
}
}
#[cfg(test)]
mod tests;