bitwarden_logging/
event.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6#[cfg(feature = "wasm")]
7use {tsify::Tsify, wasm_bindgen::prelude::*};
8
9use crate::visitor::MessageVisitor;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(rename_all = "camelCase")]
14#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
15pub struct FlightRecorderEvent {
16 pub timestamp: i64,
18 pub level: String,
20 pub target: String,
22 pub message: String,
24 #[cfg_attr(feature = "wasm", tsify(type = "Record<string, string>"))]
26 pub fields: HashMap<String, String>,
27}
28
29impl From<&tracing::Event<'_>> for FlightRecorderEvent {
30 fn from(event: &tracing::Event<'_>) -> Self {
31 let mut visitor = MessageVisitor::default();
32 event.record(&mut visitor);
33
34 Self {
35 timestamp: chrono::Utc::now().timestamp_millis(),
36 level: event.metadata().level().to_string(),
37 target: event.metadata().target().to_string(),
38 message: visitor.message,
39 fields: visitor.fields,
40 }
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn test_event_serialization_roundtrip() {
50 let event = FlightRecorderEvent {
51 timestamp: 1234567890,
52 level: "INFO".to_string(),
53 target: "test::module".to_string(),
54 message: "Test message".to_string(),
55 fields: HashMap::new(),
56 };
57
58 let json = serde_json::to_string(&event).expect("should serialize");
59 let deserialized: FlightRecorderEvent =
60 serde_json::from_str(&json).expect("should deserialize");
61
62 assert_eq!(deserialized.timestamp, 1234567890);
63 assert_eq!(deserialized.level, "INFO");
64 assert_eq!(deserialized.target, "test::module");
65 assert_eq!(deserialized.message, "Test message");
66 assert!(deserialized.fields.is_empty());
67 }
68
69 #[test]
70 fn test_event_with_fields() {
71 let mut fields = HashMap::new();
72 fields.insert("user_id".to_string(), "abc-123".to_string());
73 fields.insert("action".to_string(), "login".to_string());
74
75 let event = FlightRecorderEvent {
76 timestamp: 0,
77 level: "INFO".to_string(),
78 target: "test".to_string(),
79 message: "hello".to_string(),
80 fields,
81 };
82
83 let json = serde_json::to_string(&event).expect("should serialize");
84 assert!(json.contains("\"user_id\":\"abc-123\""));
85 assert!(json.contains("\"action\":\"login\""));
86 }
87}