rws_proxy/traffic/
config.rs1use std::path::PathBuf;
4
5pub const RWS_CONFIG_TRAFFIC_ENABLED: &str = "RWS_CONFIG_TRAFFIC_ENABLED";
6pub const RWS_CONFIG_TRAFFIC_RETENTION_DAYS: &str = "RWS_CONFIG_TRAFFIC_RETENTION_DAYS";
7pub const RWS_CONFIG_TRAFFIC_PERSIST: &str = "RWS_CONFIG_TRAFFIC_PERSIST";
8pub const RWS_CONFIG_TRAFFIC_EXCLUDE: &str = "RWS_CONFIG_TRAFFIC_EXCLUDE";
9pub const RWS_CONFIG_TRAFFIC_GEO_DB: &str = "RWS_CONFIG_TRAFFIC_GEO_DB";
10pub const RWS_CONFIG_TRAFFIC_SCRIPT: &str = "RWS_CONFIG_TRAFFIC_SCRIPT";
11pub const RWS_CONFIG_TRAFFIC_GOALS: &str = "RWS_CONFIG_TRAFFIC_GOALS";
12pub const RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV: &str = "RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV";
13
14fn read(key: &str) -> String {
15 std::env::var(key).unwrap_or_default().trim().to_string()
16}
17
18pub fn enabled_setting() -> Option<bool> {
21 match read(RWS_CONFIG_TRAFFIC_ENABLED).to_ascii_lowercase().as_str() {
22 "" => None,
23 "false" | "0" | "no" | "off" => Some(false),
24 _ => Some(true),
25 }
26}
27
28pub fn retention_days() -> u64 {
30 read(RWS_CONFIG_TRAFFIC_RETENTION_DAYS).parse::<u64>().ok().filter(|d| *d >= 1).map_or(30, |d| d.min(90))
31}
32
33pub fn exclude() -> Vec<String> {
36 let value = std::env::var(RWS_CONFIG_TRAFFIC_EXCLUDE);
37 match value {
38 Ok(v) => v.split(',').map(str::trim).filter(|p| !p.is_empty()).map(str::to_string).collect(),
39 Err(_) => ["/healthz", "/readyz", "/metrics"].iter().map(|p| p.to_string()).collect(),
40 }
41}
42
43pub fn persist_path() -> Option<PathBuf> {
48 let value = read(RWS_CONFIG_TRAFFIC_PERSIST);
49 if value.eq_ignore_ascii_case("off") {
50 return None;
51 }
52 if !value.is_empty() {
53 return Some(PathBuf::from(value));
54 }
55 [crate::entry_point::Config::RWS_CONFIG_ACME_CERT_PATH, crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE]
56 .iter()
57 .map(|key| read(key))
58 .find(|path| !path.is_empty())
59 .and_then(|cert| PathBuf::from(cert).parent().map(|dir| dir.join("traffic.json")))
60}
61
62pub fn geo_db() -> Option<PathBuf> {
65 let value = read(RWS_CONFIG_TRAFFIC_GEO_DB);
66 (!value.is_empty()).then(|| PathBuf::from(value))
67}
68
69pub fn script() -> bool {
72 matches!(read(RWS_CONFIG_TRAFFIC_SCRIPT).to_ascii_lowercase().as_str(), "true" | "1" | "yes" | "on")
73}
74
75pub const MAX_GOALS: usize = 32;
77
78pub fn goals() -> Vec<String> {
82 read(RWS_CONFIG_TRAFFIC_GOALS).split(',').map(str::trim).filter(|g| !g.is_empty()).take(MAX_GOALS).map(str::to_string).collect()
83}
84
85pub fn database_url() -> Option<String> {
90 let name = read(RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV);
91 if name.is_empty() {
92 return None;
93 }
94 std::env::var(&name).ok().map(|v| v.trim().to_string()).filter(|v| !v.is_empty())
95}