Skip to main content

agentsight_capture/
event.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 eunomia-bpf org.
3
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6
7/// Raw event structure flowing from runners through analyzers.
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub struct Event {
10    pub timestamp: u64,
11    pub source: String,
12    pub pid: u32,
13    pub comm: String,
14    pub data: serde_json::Value,
15}
16
17impl Event {
18    /// Create a new event with current timestamp
19    #[cfg(any(test, feature = "test-support"))]
20    pub fn new(source: String, pid: u32, comm: String, data: serde_json::Value) -> Self {
21        Self {
22            timestamp: std::time::SystemTime::now()
23                .duration_since(std::time::UNIX_EPOCH)
24                .unwrap_or_default()
25                .as_millis() as u64,
26            source,
27            pid,
28            comm,
29            data,
30        }
31    }
32
33    /// Create a new event with custom timestamp
34    pub fn new_with_timestamp(
35        timestamp: u64,
36        source: String,
37        pid: u32,
38        comm: String,
39        data: serde_json::Value,
40    ) -> Self {
41        Self {
42            timestamp,
43            source,
44            pid,
45            comm,
46            data,
47        }
48    }
49
50    /// Get the event timestamp as a `DateTime<Utc>`.
51    pub fn datetime(&self) -> DateTime<Utc> {
52        DateTime::from_timestamp_millis(self.timestamp as i64).unwrap_or_else(Utc::now)
53    }
54
55    /// Deserialize an event from JSON string
56    #[cfg(test)]
57    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
58        serde_json::from_str(json)
59    }
60}
61
62impl std::fmt::Display for Event {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(
65            f,
66            "[{}] {} ({}:{}): {}",
67            self.datetime().format("%Y-%m-%d %H:%M:%S%.3f"),
68            self.source,
69            self.comm,
70            self.pid,
71            self.data
72        )
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use serde_json::json;
80
81    #[test]
82    fn test_event_creation() {
83        let data = json!({"key": "value", "number": 42});
84        let event = Event::new(
85            "test-source".to_string(),
86            1234,
87            "test-comm".to_string(),
88            data.clone(),
89        );
90
91        assert!(event.timestamp > 0);
92        assert_eq!(event.source, "test-source");
93        assert_eq!(event.pid, 1234);
94        assert_eq!(event.comm, "test-comm");
95        assert_eq!(event.data, data);
96    }
97
98    #[test]
99    fn test_event_with_custom_timestamp() {
100        let data = json!({"test": true});
101        let custom_timestamp = 1234567890u64;
102
103        let event = Event::new_with_timestamp(
104            custom_timestamp,
105            "custom-source".to_string(),
106            5678,
107            "custom-comm".to_string(),
108            data.clone(),
109        );
110
111        assert_eq!(event.timestamp, custom_timestamp);
112        assert_eq!(event.source, "custom-source");
113        assert_eq!(event.pid, 5678);
114        assert_eq!(event.comm, "custom-comm");
115        assert_eq!(event.data, data);
116    }
117
118    #[test]
119    fn test_event_json_serialization() {
120        let data = json!({"message": "hello world"});
121        let event = Event::new_with_timestamp(
122            1000,
123            "test".to_string(),
124            9999,
125            "test-comm".to_string(),
126            data,
127        );
128
129        let json_str = serde_json::to_string(&event).unwrap();
130        let deserialized = Event::from_json(&json_str).unwrap();
131
132        assert_eq!(event, deserialized);
133    }
134
135    #[test]
136    fn test_event_display() {
137        let data = json!({"msg": "test"});
138        let event = Event::new_with_timestamp(
139            1609459200000, // 2021-01-01 00:00:00 UTC
140            "test-source".to_string(),
141            777,
142            "display-comm".to_string(),
143            data,
144        );
145
146        let display_str = format!("{}", event);
147        assert!(display_str.contains("test-source"));
148        assert!(display_str.contains("2021"));
149        assert!(display_str.contains("display-comm"));
150        assert!(display_str.contains("777"));
151    }
152}