1use serde::{Deserialize, Serialize};
7use std::path::PathBuf;
8
9#[derive(Debug, Clone, Serialize, Deserialize, Default)]
15pub struct ObservabilityConfig {
16 #[serde(default)]
18 pub metrics: MetricsConfig,
19
20 #[serde(default)]
22 pub logging: LoggingConfig,
23
24 #[serde(default)]
26 pub tracing: Option<TracingConfig>,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct MetricsConfig {
36 #[serde(default = "default_true")]
38 pub enabled: bool,
39
40 #[serde(default = "default_metrics_address")]
42 pub address: String,
43
44 #[serde(default = "default_metrics_path")]
46 pub path: String,
47
48 #[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#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct LoggingConfig {
71 #[serde(default = "default_log_level")]
73 pub level: String,
74
75 #[serde(default = "default_log_format")]
77 pub format: String,
78
79 #[serde(default = "default_true")]
81 pub timestamps: bool,
82
83 pub file: Option<PathBuf>,
85
86 #[serde(default)]
88 pub access_log: Option<AccessLogConfig>,
89
90 #[serde(default)]
92 pub error_log: Option<ErrorLogConfig>,
93
94 #[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#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct AccessLogConfig {
116 #[serde(default = "default_true")]
118 pub enabled: bool,
119
120 #[serde(default = "default_access_log_file")]
122 pub file: PathBuf,
123
124 #[serde(default = "default_access_log_format")]
126 pub format: String,
127
128 #[serde(default = "default_buffer_size")]
130 pub buffer_size: usize,
131
132 #[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#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct ErrorLogConfig {
152 #[serde(default = "default_true")]
154 pub enabled: bool,
155
156 #[serde(default = "default_error_log_file")]
158 pub file: PathBuf,
159
160 #[serde(default = "default_error_log_level")]
162 pub level: String,
163
164 #[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#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct AuditLogConfig {
183 #[serde(default = "default_true")]
185 pub enabled: bool,
186
187 #[serde(default = "default_audit_log_file")]
189 pub file: PathBuf,
190
191 #[serde(default = "default_buffer_size")]
193 pub buffer_size: usize,
194
195 #[serde(default = "default_true")]
197 pub log_blocked: bool,
198
199 #[serde(default = "default_true")]
201 pub log_agent_decisions: bool,
202
203 #[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#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct TracingConfig {
228 pub backend: TracingBackend,
230
231 #[serde(default = "default_sampling_rate")]
233 pub sampling_rate: f64,
234
235 #[serde(default = "default_service_name")]
237 pub service_name: String,
238}
239
240#[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
249fn 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}