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
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}