ultrafast_mcp_monitoring/
config.rs

1//! Configuration for monitoring and observability
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::time::Duration;
6
7/// Main monitoring configuration
8#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9pub struct MonitoringConfig {
10    /// Tracing configuration
11    pub tracing: TracingConfig,
12    /// Metrics configuration
13    pub metrics: MetricsConfig,
14    /// Health check configuration
15    pub health: HealthConfig,
16    /// HTTP server configuration for metrics endpoints
17    pub http: HttpConfig,
18}
19
20/// Tracing configuration
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct TracingConfig {
23    /// Enable tracing
24    pub enabled: bool,
25    /// Service name for tracing
26    pub service_name: String,
27    /// Service version
28    pub service_version: String,
29    /// Environment (dev, staging, prod)
30    pub environment: String,
31    /// Jaeger configuration
32    pub jaeger: Option<JaegerConfig>,
33    /// OTLP configuration
34    pub otlp: Option<OtlpConfig>,
35    /// Console exporter for development
36    pub console: bool,
37    /// Log level filter
38    pub level: String,
39    /// Sample rate (0.0 to 1.0)
40    pub sample_rate: f32,
41}
42
43/// Metrics configuration
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct MetricsConfig {
46    /// Enable metrics collection
47    pub enabled: bool,
48    /// Prometheus configuration
49    pub prometheus: Option<PrometheusConfig>,
50    /// OTLP metrics configuration
51    pub otlp: Option<OtlpConfig>,
52    /// Collection interval for system metrics
53    pub collection_interval: Duration,
54    /// Enable system metrics
55    pub system_metrics: bool,
56}
57
58/// Health check configuration
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct HealthConfig {
61    /// Enable health checks
62    pub enabled: bool,
63    /// Health check interval
64    pub check_interval: Duration,
65    /// Timeout for health checks
66    pub timeout: Duration,
67    /// Custom health checks
68    pub custom_checks: Vec<String>,
69}
70
71/// HTTP server configuration
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct HttpConfig {
74    /// Enable HTTP server
75    pub enabled: bool,
76    /// Bind address
77    pub address: String,
78    /// Port
79    pub port: u16,
80    /// Enable TLS
81    pub tls: Option<TlsConfig>,
82}
83
84/// Jaeger configuration
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct JaegerConfig {
87    /// Jaeger agent endpoint
88    pub agent_endpoint: String,
89    /// Jaeger collector endpoint
90    pub collector_endpoint: Option<String>,
91    /// Authentication headers
92    pub headers: HashMap<String, String>,
93}
94
95/// OTLP configuration
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct OtlpConfig {
98    /// OTLP endpoint
99    pub endpoint: String,
100    /// Authentication headers
101    pub headers: HashMap<String, String>,
102    /// Timeout
103    pub timeout: Duration,
104    /// Compression
105    pub compression: Option<String>,
106}
107
108/// Prometheus configuration
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct PrometheusConfig {
111    /// Registry name
112    pub registry_name: String,
113    /// Metrics prefix
114    pub prefix: String,
115    /// Custom labels
116    pub labels: HashMap<String, String>,
117}
118
119/// TLS configuration
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct TlsConfig {
122    /// Certificate file path
123    pub cert_file: String,
124    /// Private key file path
125    pub key_file: String,
126}
127
128impl Default for TracingConfig {
129    fn default() -> Self {
130        Self {
131            enabled: true,
132            service_name: "ultrafast-mcp".to_string(),
133            service_version: env!("CARGO_PKG_VERSION").to_string(),
134            environment: "development".to_string(),
135            jaeger: Some(JaegerConfig::default()),
136            otlp: None,
137            console: true,
138            level: "info".to_string(),
139            sample_rate: 1.0,
140        }
141    }
142}
143
144impl Default for MetricsConfig {
145    fn default() -> Self {
146        Self {
147            enabled: true,
148            prometheus: Some(PrometheusConfig::default()),
149            otlp: None,
150            collection_interval: Duration::from_secs(30),
151            system_metrics: true,
152        }
153    }
154}
155
156impl Default for HealthConfig {
157    fn default() -> Self {
158        Self {
159            enabled: true,
160            check_interval: Duration::from_secs(30),
161            timeout: Duration::from_secs(5),
162            custom_checks: vec![],
163        }
164    }
165}
166
167impl Default for HttpConfig {
168    fn default() -> Self {
169        Self {
170            enabled: true,
171            address: "127.0.0.1".to_string(),
172            port: 9090,
173            tls: None,
174        }
175    }
176}
177
178impl Default for JaegerConfig {
179    fn default() -> Self {
180        Self {
181            agent_endpoint: "http://localhost:14268/api/traces".to_string(),
182            collector_endpoint: None,
183            headers: HashMap::new(),
184        }
185    }
186}
187
188impl Default for PrometheusConfig {
189    fn default() -> Self {
190        Self {
191            registry_name: "ultrafast_mcp".to_string(),
192            prefix: "mcp".to_string(),
193            labels: HashMap::new(),
194        }
195    }
196}
197
198impl MonitoringConfig {
199    /// Load configuration from environment variables
200    pub fn from_env() -> Self {
201        let mut config = Self::default();
202
203        // Override with environment variables
204        if let Ok(val) = std::env::var("MCP_TRACING_ENABLED") {
205            config.tracing.enabled = val.parse().unwrap_or(true);
206        }
207
208        if let Ok(val) = std::env::var("MCP_SERVICE_NAME") {
209            config.tracing.service_name = val;
210        }
211
212        if let Ok(val) = std::env::var("MCP_ENVIRONMENT") {
213            config.tracing.environment = val;
214        }
215
216        if let Ok(val) = std::env::var("MCP_LOG_LEVEL") {
217            config.tracing.level = val;
218        }
219
220        if let Ok(val) = std::env::var("MCP_JAEGER_ENDPOINT") {
221            if let Some(jaeger) = config.tracing.jaeger.as_mut() {
222                jaeger.agent_endpoint = val;
223            }
224        }
225
226        if let Ok(val) = std::env::var("MCP_METRICS_ENABLED") {
227            config.metrics.enabled = val.parse().unwrap_or(true);
228        }
229
230        if let Ok(val) = std::env::var("MCP_HTTP_PORT") {
231            config.http.port = val.parse().unwrap_or(9090);
232        }
233
234        config
235    }
236
237    /// Load configuration from a file
238    #[cfg(feature = "config-files")]
239    pub fn from_file(path: &str) -> anyhow::Result<Self> {
240        let content = std::fs::read_to_string(path)?;
241        let config = match path.split('.').next_back() {
242            Some("toml") => toml::from_str(&content)?,
243            #[cfg(feature = "config-files")]
244            Some("yaml") | Some("yml") => serde_yaml::from_str(&content)?,
245            Some("json") => serde_json::from_str(&content)?,
246            _ => return Err(anyhow::anyhow!("Unsupported file format")),
247        };
248        Ok(config)
249    }
250
251    /// Load configuration from a file (no-op without config-files feature)
252    #[cfg(not(feature = "config-files"))]
253    pub fn from_file(_path: &str) -> anyhow::Result<Self> {
254        Err(anyhow::anyhow!(
255            "Config file support not enabled. Enable 'config-files' feature."
256        ))
257    }
258}