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}
38pub trait ObservabilityClient: Send + Sync + 'static + OpsStatsEventObserver {
39    fn init(&self);
40    fn increment(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
41    fn gauge(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
42    fn dist(&self, metric_name: String, value: f64, tags: Option<HashMap<String, String>>);
43    // This is needed since upper casting is not officially supported yet
44    // (WIP to support https://github.com/rust-lang/rust/issues/65991)
45    // For implementation, just return Self; should be sufficient
46    fn to_ops_stats_event_observer(self: Arc<Self>) -> Arc<dyn OpsStatsEventObserver>;
47}
48
49#[async_trait]
50impl<T: ObservabilityClient> OpsStatsEventObserver for T {
51    async fn handle_event(&self, event: OpsStatsEvent) {
52        if let OpsStatsEvent::Observability(data) = event {
53            let metric_name = format!("statsig.sdk.{}", data.clone().metric_name);
54            match data.clone().metric_type {
55                MetricType::Increment => self.increment(metric_name, data.value, data.tags),
56                MetricType::Gauge => self.gauge(metric_name, data.value, data.tags),
57                MetricType::Dist => self.dist(metric_name, data.value, data.tags),
58            };
59        }
60    }
61}