Skip to main content

scouter_settings/
storage.rs

1use crate::ScouterServerConfig;
2use scouter_types::StorageType;
3use serde::Serialize;
4use std::path::PathBuf;
5
6#[derive(Debug, Clone, Serialize)]
7pub struct ObjectStorageSettings {
8    pub storage_uri: String,
9    pub storage_type: StorageType,
10    pub region: String, // this is aws specific
11    /// How often the Delta Lake compaction (Z-ORDER optimize) runs for trace tables. Default: 24h.
12    pub trace_compaction_interval_hours: u64,
13    /// How often the span buffer flushes to Delta Lake. Default: 5s.
14    pub trace_flush_interval_secs: u64,
15}
16
17impl Default for ObjectStorageSettings {
18    fn default() -> Self {
19        let storage_uri = std::env::var("SCOUTER_STORAGE_URI")
20            .unwrap_or_else(|_| "./scouter_storage".to_string());
21
22        let storage_type = ScouterServerConfig::get_storage_type(&storage_uri);
23
24        // need to set this for aws objectstore
25        let region = std::env::var("AWS_REGION").unwrap_or_else(|_| "us-east-1".to_string());
26
27        let trace_compaction_interval_hours =
28            std::env::var("SCOUTER_TRACE_COMPACTION_INTERVAL_HOURS")
29                .ok()
30                .and_then(|v| v.parse().ok())
31                .unwrap_or(24u64);
32
33        let trace_flush_interval_secs = std::env::var("SCOUTER_TRACE_FLUSH_INTERVAL_SECS")
34            .ok()
35            .and_then(|v| v.parse().ok())
36            .unwrap_or(5u64);
37
38        Self {
39            storage_uri,
40            storage_type,
41            region,
42            trace_compaction_interval_hours,
43            trace_flush_interval_secs,
44        }
45    }
46}
47
48impl ObjectStorageSettings {
49    /// Buffer size for trace span batching before flushing to Delta Lake.
50    ///
51    /// Configurable via `SCOUTER_TRACE_BUFFER_SIZE`. Larger values produce fewer,
52    /// bigger Parquet files — reducing Delta log replay cost and file-open overhead
53    /// on cloud storage at the expense of slightly longer flush intervals.
54    /// Default: 10,000 spans.
55    pub fn trace_buffer_size(&self) -> usize {
56        std::env::var("SCOUTER_TRACE_BUFFER_SIZE")
57            .ok()
58            .and_then(|v| v.parse().ok())
59            .unwrap_or(10_000)
60    }
61
62    /// Maximum size (in MB) of the object store range cache used to avoid
63    /// redundant cloud round-trips for immutable Parquet footer reads.
64    ///
65    /// Configurable via `SCOUTER_OBJECT_CACHE_MB`. Default: 64 MB.
66    pub fn object_cache_mb(&self) -> u64 {
67        std::env::var("SCOUTER_OBJECT_CACHE_MB")
68            .ok()
69            .and_then(|v| v.parse().ok())
70            .unwrap_or(64)
71    }
72
73    pub fn storage_root(&self) -> String {
74        match self.storage_type {
75            StorageType::Google | StorageType::Aws | StorageType::Azure => {
76                if let Some(stripped) = self.storage_uri.strip_prefix("gs://") {
77                    stripped.split('/').next().unwrap_or(stripped).to_string()
78                } else if let Some(stripped) = self.storage_uri.strip_prefix("s3://") {
79                    stripped.split('/').next().unwrap_or(stripped).to_string()
80                } else if let Some(stripped) = self.storage_uri.strip_prefix("az://") {
81                    stripped.split('/').next().unwrap_or(stripped).to_string()
82                } else {
83                    self.storage_uri.clone()
84                }
85            }
86            StorageType::Local => {
87                // For local storage, just return the path directly
88                self.storage_uri.clone()
89            }
90        }
91    }
92
93    pub fn canonicalized_path(&self) -> String {
94        // if registry is local canonicalize the path
95        if self.storage_type == StorageType::Local {
96            let path = PathBuf::from(&self.storage_uri);
97            if path.exists() {
98                path.canonicalize()
99                    .unwrap_or_else(|_| path.clone())
100                    .to_str()
101                    .unwrap()
102                    .to_string()
103            } else {
104                self.storage_uri.clone()
105            }
106        } else {
107            self.storage_uri.clone()
108        }
109    }
110}