statsig_rust/observability/
observability_client_adapter.rs

1use std::{collections::HashMap, sync::Arc};
2
3use async_trait::async_trait;
4
5use crate::observability::ops_stats::OpsStatsEventObserver;
6
7use super::ops_stats::OpsStatsEvent;
8#[derive(Clone)]
9pub enum MetricType {
10    Increment,
11    Gauge,
12    Dist,
13}
14
15#[derive(Clone)]
16pub struct ObservabilityEvent {
17    pub metric_type: MetricType,
18    pub metric_name: String,
19    pub value: f64,
20    pub tags: Option<HashMap<String, String>>,
21}
22
23impl ObservabilityEvent {
24    pub fn new_event(
25        metric_type: MetricType,
26        metric_name: String,
27        value: f64,
28        tags: Option<HashMap<String, String>>,
29    ) -> OpsStatsEvent {
30        OpsStatsEvent::Observability(ObservabilityEvent {
31            metric_type,
32            metric_name,
33            value,
34            tags,
35        })
36    }
37}
38
39pub trait ObservabilityClient: Send + Sync + 'static + OpsStatsEventObserver {
40    fn init(&self);
41    fn increment(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
42    fn gauge(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
43    fn dist(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
44    fn error(&self, tag: String, error: String);
45    // This is needed since upper casting is not officially supported yet
46    // (WIP to support https://github.com/rust-lang/rust/issues/65991)
47    // For implementation, just return Self; should be sufficient
48    fn to_ops_stats_event_observer(self: Arc<Self>) -> Arc<dyn OpsStatsEventObserver>;
49}
50
51#[async_trait]
52impl<T: ObservabilityClient> OpsStatsEventObserver for T {
53    async fn handle_event(&self, event: OpsStatsEvent) {
54        match event {
55            OpsStatsEvent::Observability(data) => {
56                let metric_name = format!("statsig.sdk.{}", data.clone().metric_name);
57                match data.clone().metric_type {
58                    MetricType::Increment => self.increment(metric_name, data.value, data.tags),
59                    MetricType::Gauge => self.gauge(metric_name, data.value, data.tags),
60                    MetricType::Dist => self.dist(metric_name, data.value, data.tags),
61                };
62            }
63            OpsStatsEvent::SDKError(error) => {
64                self.error(error.tag, error.exception);
65            }
66            _ => {}
67        }
68    }
69}