sentinel_config/
observability.rs

1//! Observability configuration types
2//!
3//! This module contains configuration types for metrics, logging,
4//! and distributed tracing.
5
6use serde::{Deserialize, Serialize};
7use std::path::PathBuf;
8
9// ============================================================================
10// Observability Configuration
11// ============================================================================
12
13/// Observability configuration
14#[derive(Debug, Clone, Serialize, Deserialize, Default)]
15pub struct ObservabilityConfig {
16    /// Metrics configuration
17    #[serde(default)]
18    pub metrics: MetricsConfig,
19
20    /// Logging configuration
21    #[serde(default)]
22    pub logging: LoggingConfig,
23
24    /// Tracing configuration
25    #[serde(default)]
26    pub tracing: Option<TracingConfig>,
27}
28
29// ============================================================================
30// Metrics Configuration
31// ============================================================================
32
33/// Metrics configuration
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct MetricsConfig {
36    /// Enable metrics collection
37    #[serde(default = "default_true")]
38    pub enabled: bool,
39
40    /// Metrics endpoint address
41    #[serde(default = "default_metrics_address")]
42    pub address: String,
43
44    /// Metrics path
45    #[serde(default = "default_metrics_path")]
46    pub path: String,
47
48    /// Include high-cardinality metrics
49    #[serde(default)]
50    pub high_cardinality: bool,
51}
52
53impl Default for MetricsConfig {
54    fn default() -> Self {
55        Self {
56            enabled: default_true(),
57            address: default_metrics_address(),
58            path: default_metrics_path(),
59            high_cardinality: false,
60        }
61    }
62}
63
64// ============================================================================
65// Logging Configuration
66// ============================================================================
67
68/// Logging configuration
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct LoggingConfig {
71    /// Log level
72    #[serde(default = "default_log_level")]
73    pub level: String,
74
75    /// Log format (json, pretty)
76    #[serde(default = "default_log_format")]
77    pub format: String,
78
79    /// Include timestamps
80    #[serde(default = "default_true")]
81    pub timestamps: bool,
82
83    /// Application log file path (stdout if not specified)
84    pub file: Option<PathBuf>,
85
86    /// Access log configuration
87    #[serde(default)]
88    pub access_log: Option<AccessLogConfig>,
89
90    /// Error log configuration
91    #[serde(default)]
92    pub error_log: Option<ErrorLogConfig>,
93
94    /// Audit log configuration (security events)
95    #[serde(default)]
96    pub audit_log: Option<AuditLogConfig>,
97}
98
99impl Default for LoggingConfig {
100    fn default() -> Self {
101        Self {
102            level: default_log_level(),
103            format: default_log_format(),
104            timestamps: default_true(),
105            file: None,
106            access_log: None,
107            error_log: None,
108            audit_log: None,
109        }
110    }
111}
112
113/// Access log configuration
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct AccessLogConfig {
116    /// Enable access logging
117    #[serde(default = "default_true")]
118    pub enabled: bool,
119
120    /// Access log file path
121    #[serde(default = "default_access_log_file")]
122    pub file: PathBuf,
123
124    /// Log format (combined, json, custom)
125    #[serde(default = "default_access_log_format")]
126    pub format: String,
127
128    /// Buffer size for writes
129    #[serde(default = "default_buffer_size")]
130    pub buffer_size: usize,
131
132    /// Include trace_id in logs
133    #[serde(default = "default_true")]
134    pub include_trace_id: bool,
135}
136
137impl Default for AccessLogConfig {
138    fn default() -> Self {
139        Self {
140            enabled: true,
141            file: default_access_log_file(),
142            format: default_access_log_format(),
143            buffer_size: default_buffer_size(),
144            include_trace_id: true,
145        }
146    }
147}
148
149/// Error log configuration
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct ErrorLogConfig {
152    /// Enable error logging
153    #[serde(default = "default_true")]
154    pub enabled: bool,
155
156    /// Error log file path
157    #[serde(default = "default_error_log_file")]
158    pub file: PathBuf,
159
160    /// Minimum level for error log (warn, error)
161    #[serde(default = "default_error_log_level")]
162    pub level: String,
163
164    /// Buffer size for writes
165    #[serde(default = "default_buffer_size")]
166    pub buffer_size: usize,
167}
168
169impl Default for ErrorLogConfig {
170    fn default() -> Self {
171        Self {
172            enabled: true,
173            file: default_error_log_file(),
174            level: default_error_log_level(),
175            buffer_size: default_buffer_size(),
176        }
177    }
178}
179
180/// Audit log configuration (security events)
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct AuditLogConfig {
183    /// Enable audit logging
184    #[serde(default = "default_true")]
185    pub enabled: bool,
186
187    /// Audit log file path
188    #[serde(default = "default_audit_log_file")]
189    pub file: PathBuf,
190
191    /// Buffer size for writes
192    #[serde(default = "default_buffer_size")]
193    pub buffer_size: usize,
194
195    /// Log blocked requests
196    #[serde(default = "default_true")]
197    pub log_blocked: bool,
198
199    /// Log agent decisions
200    #[serde(default = "default_true")]
201    pub log_agent_decisions: bool,
202
203    /// Log WAF events
204    #[serde(default = "default_true")]
205    pub log_waf_events: bool,
206}
207
208impl Default for AuditLogConfig {
209    fn default() -> Self {
210        Self {
211            enabled: true,
212            file: default_audit_log_file(),
213            buffer_size: default_buffer_size(),
214            log_blocked: true,
215            log_agent_decisions: true,
216            log_waf_events: true,
217        }
218    }
219}
220
221// ============================================================================
222// Tracing Configuration
223// ============================================================================
224
225/// Tracing configuration
226#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct TracingConfig {
228    /// Tracing backend
229    pub backend: TracingBackend,
230
231    /// Sampling rate (0.0 - 1.0)
232    #[serde(default = "default_sampling_rate")]
233    pub sampling_rate: f64,
234
235    /// Service name
236    #[serde(default = "default_service_name")]
237    pub service_name: String,
238}
239
240/// Tracing backend
241#[derive(Debug, Clone, Serialize, Deserialize)]
242#[serde(rename_all = "snake_case")]
243pub enum TracingBackend {
244    Jaeger { endpoint: String },
245    Zipkin { endpoint: String },
246    Otlp { endpoint: String },
247}
248
249// ============================================================================
250// Default Value Functions
251// ============================================================================
252
253fn default_true() -> bool {
254    true
255}
256
257fn default_metrics_address() -> String {
258    "0.0.0.0:9090".to_string()
259}
260
261fn default_metrics_path() -> String {
262    "/metrics".to_string()
263}
264
265fn default_log_level() -> String {
266    "info".to_string()
267}
268
269fn default_log_format() -> String {
270    "json".to_string()
271}
272
273fn default_access_log_format() -> String {
274    "json".to_string()
275}
276
277fn default_buffer_size() -> usize {
278    8192
279}
280
281fn default_access_log_file() -> PathBuf {
282    PathBuf::from("/var/log/sentinel/access.log")
283}
284
285fn default_error_log_file() -> PathBuf {
286    PathBuf::from("/var/log/sentinel/error.log")
287}
288
289fn default_error_log_level() -> String {
290    "warn".to_string()
291}
292
293fn default_audit_log_file() -> PathBuf {
294    PathBuf::from("/var/log/sentinel/audit.log")
295}
296
297fn default_sampling_rate() -> f64 {
298    0.01
299}
300
301fn default_service_name() -> String {
302    "sentinel".to_string()
303}