statsig_rust/
statsig_metadata.rs

1use crate::log_e;
2use lazy_static::lazy_static;
3use parking_lot::RwLock;
4use serde::Serialize;
5use serde_json::{json, Value};
6use std::collections::HashMap;
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.10.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.try_write_for(std::time::Duration::from_secs(5)) {
64            Some(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            None => {
71                log_e!(
72                    TAG,
73                    "Failed to clone StatsigMetadata: Failed to lock STATSIG_METADATA"
74                );
75            }
76        }
77    }
78
79    pub fn update_service_name(service_name: Option<String>) {
80        match STATSIG_METADATA.try_write_for(std::time::Duration::from_secs(5)) {
81            Some(mut metadata) => {
82                metadata.service_name = service_name;
83            }
84            None => {
85                log_e!(
86                    TAG,
87                    "Failed to clone StatsigMetadata: Failed to lock STATSIG_METADATA"
88                );
89            }
90        }
91    }
92
93    #[must_use]
94    pub fn get_constant_request_headers(sdk_key: &str) -> HashMap<String, String> {
95        let meta = Self::get_metadata();
96
97        HashMap::from([
98            ("STATSIG-API-KEY".to_string(), sdk_key.to_string()),
99            ("STATSIG-SDK-TYPE".to_string(), meta.sdk_type),
100            ("STATSIG-SDK-VERSION".to_string(), meta.sdk_version),
101            ("STATSIG-SERVER-SESSION-ID".to_string(), meta.session_id),
102        ])
103    }
104
105    #[must_use]
106    pub fn get_metadata() -> StatsigMetadata {
107        match STATSIG_METADATA.try_read_for(std::time::Duration::from_secs(5)) {
108            Some(metadata) => metadata.clone(),
109            None => {
110                log_e!(
111                    TAG,
112                    "Failed to clone StatsigMetadata: Failed to lock STATSIG_METADATA"
113                );
114                StatsigMetadata::new()
115            }
116        }
117    }
118
119    #[must_use]
120    pub fn get_as_json() -> Value {
121        json!(StatsigMetadata::get_metadata())
122    }
123
124    #[must_use]
125    pub fn get_with_log_event_extras(
126        flushing_interval_ms: u64,
127        batch_size: usize,
128        max_pending_batches: usize,
129        flush_type: String,
130    ) -> StatsigMetadataWithLogEventExtras {
131        StatsigMetadataWithLogEventExtras {
132            base: StatsigMetadata::get_metadata(),
133            flushing_interval_ms,
134            batch_size,
135            max_pending_batches,
136            flush_type,
137        }
138    }
139}