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}