Expand description
§Asynchronous event support
Plugins with async events capability can enrich an event stream from a given source (not necessarily implemented by itself) by injecting events asynchronously in the stream. Such a feature can be used for implementing notification systems or recording state transitions in the event-driven model of the Falcosecurity libraries, so that they can be available to other components at runtime or when the event stream is replayed through a capture file.
For example, the Falcosecurity libraries leverage this feature internally to implement metadata enrichment systems such as the one related to container runtimes. In that case, the libraries implement asynchronous jobs responsible for retrieving such information externally outside the main event processing loop so that it’s non-blocking. The worker jobs produce a notification event every time a new container is detected and inject it asynchronously in the system event stream to be later processed for state updates and for evaluating Falco rules.
For your plugin to support asynchronous events, you will need to implement the async_event::AsyncEventPlugin
trait and invoke the async_event
macro, for example:
use std::ffi::{CStr, CString};
use std::sync::Arc;
use std::thread::JoinHandle;
use falco_plugin::anyhow::Error;
use falco_plugin::event::events::Event;
use falco_plugin::event::events::EventMetadata;
use falco_plugin::base::Plugin;
use falco_plugin::{async_event_plugin, plugin};
use falco_plugin::async_event::{
AsyncEventPlugin,
AsyncHandler,
BackgroundTask};
use falco_plugin::tables::TablesInput;
struct MyAsyncPlugin {
task: Arc<BackgroundTask>,
thread: Option<JoinHandle<Result<(), Error>>>,
}
impl Plugin for MyAsyncPlugin {
// ...
}
impl AsyncEventPlugin for MyAsyncPlugin {
const ASYNC_EVENTS: &'static [&'static str] = &[]; // generate any async events
const EVENT_SOURCES: &'static [&'static str] = &[]; // attach to all event sources
fn start_async(&mut self, handler: AsyncHandler) -> Result<(), Error> {
// stop the thread if it was already running
if self.thread.is_some() {
self.stop_async()?;
}
// start a new thread
// waiting up to 100ms between events for the stop request
self.thread = Some(self.task.spawn(std::time::Duration::from_millis(100), move || {
// submit an async event to the main event loop
handler.emit(Self::async_event(c"sample_async", b"hello"))?;
Ok(())
})?);
Ok(())
}
fn stop_async(&mut self) -> Result<(), Error> {
self.task.request_stop_and_notify()?;
let Some(handle) = self.thread.take() else {
return Ok(());
};
match handle.join() {
Ok(res) => res,
Err(e) => std::panic::resume_unwind(e),
}
}
}
plugin!(MyAsyncPlugin);
async_event_plugin!(MyAsyncPlugin);
Structs§
- Async
Event - The event type that can be emitted from async event plugins
- Async
Handler - A handle to emit asynchronous events
- Background
Task - A helper to periodically run a background task until shutdown is requested
Traits§
- Async
Event Plugin - Support for asynchronous event plugins