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