statsig_client/
config.rs

1use bon::Builder;
2use serde::{Deserialize, Serialize};
3use std::time::Duration;
4
5#[derive(Debug, Clone, Builder)]
6pub struct StatsigClientConfig {
7    #[builder(into)]
8    pub api_key: String,
9    #[builder(default = "https://api.statsig.com".to_string())]
10    pub base_url: String,
11    #[builder(default = "https://events.statsigapi.net".to_string())]
12    pub events_base_url: String,
13    #[builder(default = Duration::from_secs(30))]
14    pub timeout: Duration,
15    #[builder(default = 3)]
16    pub retry_attempts: u32,
17    #[builder(default = Duration::from_millis(1000))]
18    pub retry_delay: Duration,
19    #[builder(default = Duration::from_secs(300))]
20    pub cache_ttl: Duration,
21    #[builder(default = 10000)]
22    pub cache_max_capacity: u64,
23    #[builder(default = 10)]
24    pub batch_size: usize,
25    #[builder(default = Duration::from_millis(100))]
26    pub batch_flush_interval: Duration,
27    #[builder(default = false)]
28    pub offline_fallback: bool,
29    #[builder(default = false)]
30    pub exposure_logging_disabled: bool,
31    #[builder(default = "rust-client".to_string())]
32    pub sdk_type: String,
33    #[builder(default = env!("CARGO_PKG_VERSION").to_string())]
34    pub sdk_version: String,
35}
36
37impl StatsigClientConfig {
38    pub fn new(api_key: impl Into<String>) -> crate::error::Result<Self> {
39        let api_key = api_key.into();
40
41        if api_key.is_empty() {
42            return Err(crate::error::StatsigError::configuration(
43                "API key cannot be empty",
44            ));
45        }
46
47        Ok(Self::builder().api_key(api_key).build())
48    }
49
50    pub fn validate(&self) -> crate::error::Result<()> {
51        if self.api_key.is_empty() {
52            return Err(crate::error::StatsigError::configuration(
53                "API key cannot be empty",
54            ));
55        }
56
57        if self.base_url.is_empty() {
58            return Err(crate::error::StatsigError::configuration(
59                "Base URL cannot be empty",
60            ));
61        }
62
63        if self.timeout.as_secs() == 0 {
64            return Err(crate::error::StatsigError::configuration(
65                "Timeout must be greater than 0",
66            ));
67        }
68
69        if self.retry_attempts == 0 {
70            return Err(crate::error::StatsigError::configuration(
71                "Retry attempts must be greater than 0",
72            ));
73        }
74
75        if self.batch_size == 0 {
76            return Err(crate::error::StatsigError::configuration(
77                "Batch size must be greater than 0",
78            ));
79        }
80
81        if self.cache_ttl.as_secs() == 0 {
82            return Err(crate::error::StatsigError::configuration(
83                "Cache TTL must be greater than 0",
84            ));
85        }
86
87        Ok(())
88    }
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct ClientInfo {
93    pub sdk_type: String,
94    pub sdk_version: String,
95    pub language: String,
96    pub language_version: String,
97}
98
99impl Default for ClientInfo {
100    fn default() -> Self {
101        Self {
102            sdk_type: "rust-client".to_string(),
103            sdk_version: env!("CARGO_PKG_VERSION").to_string(),
104            language: "rust".to_string(),
105            language_version: "unknown".to_string(),
106        }
107    }
108}