rustfs_obs/entry/
unified.rs1use crate::{AuditLogEntry, BaseLogEntry, LogKind, LogRecord, SerializableLevel};
16use chrono::{DateTime, Utc};
17use serde::{Deserialize, Serialize};
18use tracing_core::Level;
19
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
47pub struct ServerLogEntry {
48 #[serde(flatten)]
49 pub base: BaseLogEntry,
50
51 pub level: SerializableLevel,
52 pub source: String,
53
54 #[serde(rename = "userId", skip_serializing_if = "Option::is_none")]
55 pub user_id: Option<String>,
56
57 #[serde(skip_serializing_if = "Vec::is_empty", default)]
58 pub fields: Vec<(String, String)>,
59}
60
61impl ServerLogEntry {
62 pub fn new(level: Level, source: String) -> Self {
64 ServerLogEntry {
65 base: BaseLogEntry::new(),
66 level: SerializableLevel(level),
67 source,
68 user_id: None,
69 fields: Vec::new(),
70 }
71 }
72
73 pub fn with_base(mut self, base: BaseLogEntry) -> Self {
75 self.base = base;
76 self
77 }
78
79 pub fn user_id(mut self, user_id: Option<String>) -> Self {
81 self.user_id = user_id;
82 self
83 }
84
85 pub fn fields(mut self, fields: Vec<(String, String)>) -> Self {
87 self.fields = fields;
88 self
89 }
90
91 pub fn add_field(mut self, key: String, value: String) -> Self {
93 self.fields.push((key, value));
94 self
95 }
96}
97
98impl LogRecord for ServerLogEntry {
99 fn to_json(&self) -> String {
100 serde_json::to_string(self).unwrap_or_else(|_| String::from("{}"))
101 }
102
103 fn get_timestamp(&self) -> DateTime<Utc> {
104 self.base.timestamp
105 }
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ConsoleLogEntry {
134 #[serde(flatten)]
135 pub base: BaseLogEntry,
136
137 pub level: LogKind,
138 pub console_msg: String,
139 pub node_name: String,
140
141 #[serde(skip)]
142 pub err: Option<String>,
143}
144
145impl ConsoleLogEntry {
146 pub fn new() -> Self {
148 ConsoleLogEntry {
149 base: BaseLogEntry::new(),
150 level: LogKind::Info,
151 console_msg: String::new(),
152 node_name: String::new(),
153 err: None,
154 }
155 }
156
157 pub fn new_with_console_msg(console_msg: String, node_name: String) -> Self {
159 ConsoleLogEntry {
160 base: BaseLogEntry::new(),
161 level: LogKind::Info,
162 console_msg,
163 node_name,
164 err: None,
165 }
166 }
167
168 pub fn with_base(mut self, base: BaseLogEntry) -> Self {
170 self.base = base;
171 self
172 }
173
174 pub fn set_level(mut self, level: LogKind) -> Self {
176 self.level = level;
177 self
178 }
179
180 pub fn set_node_name(mut self, node_name: String) -> Self {
182 self.node_name = node_name;
183 self
184 }
185
186 pub fn set_console_msg(mut self, console_msg: String) -> Self {
188 self.console_msg = console_msg;
189 self
190 }
191
192 pub fn set_err(mut self, err: Option<String>) -> Self {
194 self.err = err;
195 self
196 }
197}
198
199impl Default for ConsoleLogEntry {
200 fn default() -> Self {
201 Self::new()
202 }
203}
204
205impl LogRecord for ConsoleLogEntry {
206 fn to_json(&self) -> String {
207 serde_json::to_string(self).unwrap_or_else(|_| String::from("{}"))
208 }
209
210 fn get_timestamp(&self) -> DateTime<Utc> {
211 self.base.timestamp
212 }
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
236#[serde(tag = "type")]
237pub enum UnifiedLogEntry {
238 #[serde(rename = "server")]
239 Server(ServerLogEntry),
240
241 #[serde(rename = "audit")]
242 Audit(Box<AuditLogEntry>),
243
244 #[serde(rename = "console")]
245 Console(ConsoleLogEntry),
246}
247
248impl LogRecord for UnifiedLogEntry {
249 fn to_json(&self) -> String {
250 match self {
251 UnifiedLogEntry::Server(entry) => entry.to_json(),
252 UnifiedLogEntry::Audit(entry) => entry.to_json(),
253 UnifiedLogEntry::Console(entry) => entry.to_json(),
254 }
255 }
256
257 fn get_timestamp(&self) -> DateTime<Utc> {
258 match self {
259 UnifiedLogEntry::Server(entry) => entry.get_timestamp(),
260 UnifiedLogEntry::Audit(entry) => entry.get_timestamp(),
261 UnifiedLogEntry::Console(entry) => entry.get_timestamp(),
262 }
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269
270 #[test]
271 fn test_base_log_entry() {
272 let base = BaseLogEntry::new()
273 .request_id(Some("req-123".to_string()))
274 .message(Some("Test message".to_string()));
275
276 assert_eq!(base.request_id, Some("req-123".to_string()));
277 assert_eq!(base.message, Some("Test message".to_string()));
278 }
279
280 #[test]
281 fn test_server_log_entry() {
282 let entry = ServerLogEntry::new(Level::INFO, "test_module".to_string())
283 .user_id(Some("user-456".to_string()))
284 .add_field("operation".to_string(), "login".to_string());
285
286 assert_eq!(entry.level.0, Level::INFO);
287 assert_eq!(entry.source, "test_module");
288 assert_eq!(entry.user_id, Some("user-456".to_string()));
289 assert_eq!(entry.fields.len(), 1);
290 assert_eq!(entry.fields[0], ("operation".to_string(), "login".to_string()));
291 }
292
293 #[test]
294 fn test_unified_log_entry_json() {
295 let server_entry = ServerLogEntry::new(Level::INFO, "test_source".to_string());
296 let unified = UnifiedLogEntry::Server(server_entry);
297
298 let json = unified.to_json();
299 assert!(json.contains("test_source"));
300 }
301}