Skip to main content

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