falco_event/events/
metadata.rs

1use chrono::Local;
2use std::fmt::{Debug, Formatter};
3use std::io::Write;
4use std::time::{Duration, SystemTime, UNIX_EPOCH};
5
6#[derive(Clone)]
7pub struct EventMetadata {
8    pub ts: u64,
9    pub tid: i64,
10}
11
12impl EventMetadata {
13    pub fn timestamp(&self) -> Option<SystemTime> {
14        if self.ts == u64::MAX {
15            None
16        } else {
17            Some(UNIX_EPOCH + Duration::from_nanos(self.ts))
18        }
19    }
20
21    /// Write event header
22    ///
23    /// To form a valid event, after calling this method, the caller must write out the payload
24    /// at exactly `len - 26` bytes, containing `nparam` lengths (as the proper type)
25    /// and the parameter values themselves.
26    pub fn write_header<W: Write>(
27        &self,
28        len: u32,
29        event_type: u16,
30        nparams: u32,
31        mut writer: W,
32    ) -> std::io::Result<()> {
33        writer.write_all(self.ts.to_ne_bytes().as_slice())?;
34        writer.write_all(self.tid.to_ne_bytes().as_slice())?;
35
36        writer.write_all(len.to_ne_bytes().as_slice())?;
37        writer.write_all(event_type.to_ne_bytes().as_slice())?;
38        writer.write_all(nparams.to_ne_bytes().as_slice())?;
39
40        Ok(())
41    }
42
43    /// Write event header and parameter lengths
44    ///
45    /// To form a valid event, after calling this method, the caller must write out the payload
46    /// for each parameter, `lengths[i]` bytes in length.
47    pub fn write_header_with_lengths<W: Write, L: Into<u32> + Copy, const N: usize>(
48        &self,
49        event_type: u16,
50        lengths: [L; N],
51        mut writer: W,
52    ) -> std::io::Result<()> {
53        let len = 26 + // header
54            (size_of::<L>() * lengths.len()) as u32 +
55            lengths.iter().copied().map(Into::into).sum::<u32>();
56
57        let nparams = lengths.len();
58
59        self.write_header(len, event_type, nparams as u32, &mut writer)?;
60        let lengths: &[u8] = unsafe {
61            std::slice::from_raw_parts(lengths.as_ptr().cast(), lengths.len() * size_of::<L>())
62        };
63        writer.write_all(lengths)?;
64
65        Ok(())
66    }
67}
68
69impl Debug for EventMetadata {
70    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
71        if let Some(timestamp) = self.timestamp() {
72            let dt = chrono::DateTime::<Local>::from(timestamp);
73            f.write_str(&dt.to_rfc3339_opts(chrono::SecondsFormat::AutoSi, false))?;
74        } else {
75            f.write_str("<no timestamp>")?;
76        }
77
78        write!(f, " tid={:?}", self.tid)
79    }
80}
81
82impl Default for EventMetadata {
83    fn default() -> Self {
84        Self {
85            ts: u64::MAX,
86            tid: -1,
87        }
88    }
89}