statsig_rust/
statsig_metadata.rs

1use crate::log_e;
2use lazy_static::lazy_static;
3use serde::Serialize;
4use serde_json::{json, Value};
5use std::collections::HashMap;
6use std::sync::RwLock;
7use uuid::Uuid;
8
9lazy_static! {
10    static ref STATSIG_METADATA: RwLock<StatsigMetadata> = RwLock::new(StatsigMetadata::new());
11}
12
13const TAG: &str = stringify!(StatsigMetadata);
14#[derive(Serialize, Clone)]
15#[serde(rename_all = "camelCase")]
16pub struct StatsigMetadata {
17    pub sdk_type: String,
18    pub sdk_version: String,
19
20    #[serde(rename = "sessionID")]
21    pub session_id: String,
22
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub os: Option<String>,
25
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub arch: Option<String>,
28
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub language_version: Option<String>,
31
32    #[serde(skip_serializing_if = "Option::is_none")]
33    #[serde(rename = "service_name")]
34    pub service_name: Option<String>,
35}
36
37#[derive(Serialize, Clone)]
38#[serde(rename_all = "camelCase")]
39pub struct StatsigMetadataWithLogEventExtras {
40    #[serde(flatten)]
41    pub base: StatsigMetadata,
42
43    pub flushing_interval_ms: u64,
44    pub batch_size: usize,
45    pub max_pending_batches: usize,
46    pub flush_type: String,
47}
48
49impl StatsigMetadata {
50    fn new() -> Self {
51        Self {
52            sdk_version: "0.5.2".to_string(),
53            sdk_type: "statsig-server-core".to_string(),
54            session_id: Uuid::new_v4().to_string(),
55            os: None,
56            arch: None,
57            language_version: None,
58            service_name: None,
59        }
60    }
61
62    pub fn update_values(sdk_type: String, os: String, arch: String, language_version: String) {
63        match STATSIG_METADATA.write() {
64            Ok(mut metadata) => {
65                metadata.sdk_type = sdk_type;
66                metadata.os = Some(os);
67                metadata.arch = Some(arch);
68                metadata.language_version = Some(language_version);
69            }
70            Err(e) => {
71                log_e!(TAG, "Failed to clone StatsigMetadata: {}", e.to_string());
72            }
73        }
74    }
75
76    pub fn update_service_name(service_name: Option<String>) {
77        match STATSIG_METADATA.write() {
78            Ok(mut metadata) => {
79                metadata.service_name = service_name;
80            }
81            Err(e) => {
82                log_e!(TAG, "Failed to clone StatsigMetadata: {}", e.to_string());
83            }
84        }
85    }
86
87    #[must_use]
88    pub fn get_constant_request_headers(sdk_key: &str) -> HashMap<String, String> {
89        let meta = Self::get_metadata();
90
91        HashMap::from([
92            ("STATSIG-API-KEY".to_string(), sdk_key.to_string()),
93            ("STATSIG-SDK-TYPE".to_string(), meta.sdk_type),
94            ("STATSIG-SDK-VERSION".to_string(), meta.sdk_version),
95            ("STATSIG-SERVER-SESSION-ID".to_string(), meta.session_id),
96        ])
97    }
98
99    #[must_use]
100    pub fn get_metadata() -> StatsigMetadata {
101        match STATSIG_METADATA.read() {
102            Ok(metadata) => metadata.clone(),
103            Err(e) => {
104                log_e!(TAG, "Failed to clone StatsigMetadata: {}", e.to_string());
105                StatsigMetadata::new()
106            }
107        }
108    }
109
110    #[must_use]
111    pub fn get_as_json() -> Value {
112        json!(StatsigMetadata::get_metadata())
113    }
114
115    #[must_use]
116    pub fn get_with_log_event_extras(
117        flushing_interval_ms: u64,
118        batch_size: usize,
119        max_pending_batches: usize,
120        flush_type: String,
121    ) -> StatsigMetadataWithLogEventExtras {
122        StatsigMetadataWithLogEventExtras {
123            base: StatsigMetadata::get_metadata(),
124            flushing_interval_ms,
125            batch_size,
126            max_pending_batches,
127            flush_type,
128        }
129    }
130}