statsig_rust/
statsig_metadata.rs1use 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.1";
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}