From ddbef7450da45d460368b56d0f1397d0da795bf3 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 17 Feb 2021 11:16:00 +0000 Subject: [PATCH] event_monitor: Add new crate for event reporting This crate exposes the abililty for the VMM to set a file that events should be written to. The event!() macro provides an interface to report those events allowing the specification of an event source, an event type and optional extra data. This will be written to the provided file descriptor as JSON data. Signed-off-by: Rob Bradford --- Cargo.lock | 10 ++++++ Cargo.toml | 1 + event_monitor/Cargo.toml | 11 ++++++ event_monitor/src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 event_monitor/Cargo.toml create mode 100644 event_monitor/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 1c147503b..ff4ac951d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,6 +341,16 @@ dependencies = [ "libc", ] +[[package]] +name = "event_monitor" +version = "0.1.0" +dependencies = [ + "libc", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "failure" version = "0.1.8" diff --git a/Cargo.toml b/Cargo.toml index 3b80d182a..1d899f98f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,7 @@ members = [ "arch_gen", "block_util", "devices", + "event_monitor", "hypervisor", "net_gen", "net_util", diff --git a/event_monitor/Cargo.toml b/event_monitor/Cargo.toml new file mode 100644 index 000000000..830660098 --- /dev/null +++ b/event_monitor/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "event_monitor" +version = "0.1.0" +authors = ["The Cloud Hypervisor Authors"] +edition = "2018" + +[dependencies] +libc = "0.2.86" +serde = {version = ">=1.0.27", features = ["rc"] } +serde_derive = ">=1.0.27" +serde_json = ">=1.0.9" diff --git a/event_monitor/src/lib.rs b/event_monitor/src/lib.rs new file mode 100644 index 000000000..cb58cd293 --- /dev/null +++ b/event_monitor/src/lib.rs @@ -0,0 +1,77 @@ +// Copyright © 2021 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +#[macro_use] +extern crate serde_derive; + +use std::borrow::Cow; +use std::collections::HashMap; +use std::fs::File; +use std::os::unix::io::AsRawFd; +use std::time::{Duration, Instant}; + +static mut MONITOR: Option<(File, Instant)> = None; + +/// This function must only be called once from the main process before any threads +/// are created to avoid race conditions +pub fn set_monitor(file: File) -> Result<(), std::io::Error> { + assert!(unsafe { MONITOR.is_none() }); + let fd = file.as_raw_fd(); + let ret = unsafe { + let mut flags = libc::fcntl(fd, libc::F_GETFL); + flags |= libc::O_NONBLOCK; + libc::fcntl(fd, libc::F_SETFL, flags) + }; + if ret < 0 { + return Err(std::io::Error::last_os_error()); + } + unsafe { + MONITOR = Some((file, Instant::now())); + }; + Ok(()) +} + +#[derive(Serialize)] +struct Event<'a> { + timestamp: Duration, + source: &'a str, + event: &'a str, + properties: Option<&'a HashMap, Cow<'a, str>>>, +} + +pub fn event_log(source: &str, event: &str, properties: Option<&HashMap, Cow>>) { + if let Some((file, start)) = unsafe { MONITOR.as_ref() } { + let e = Event { + timestamp: start.elapsed(), + source, + event, + properties, + }; + serde_json::to_writer_pretty(file, &e).ok(); + } +} + +/* + Through the use of Cow<'a, str> it is possible to use String as well as + &str as the parameters: + e.g. + event!("cpu_manager", "create_vcpu", "id", cpu_id.to_string()); +*/ +#[macro_export] +macro_rules! event { + ($source:expr, $event:expr) => { + $crate::event_log($source, $event, None) + }; + ($source:expr, $event:expr, $($key:expr, $value:expr),*) => { + { + let mut properties = ::std::collections::HashMap::new(); + $( + properties.insert($key.into(), $value.into()); + )+ + $crate::event_log($source, $event, Some(&properties)) + } + }; + +}