|
@@ -3,8 +3,8 @@
|
|
|
//! This is the user space side of the [Aya] logging framework. For the eBPF
|
|
|
//! side, see the `aya-log-ebpf` crate.
|
|
|
//!
|
|
|
-//! `aya-log` provides the [EbpfLogger] type, which reads log records created by
|
|
|
-//! `aya-log-ebpf` and logs them using the [log] crate. Any logger that
|
|
|
+//! `aya-log` provides functions which read log records created by
|
|
|
+//! `aya-log-ebpf` and log them using the [log] crate. Any logger that
|
|
|
//! implements the [Log] trait can be used with this crate.
|
|
|
//!
|
|
|
//! # Example:
|
|
@@ -19,7 +19,15 @@
|
|
|
//! env_logger::init();
|
|
|
//!
|
|
|
//! // start reading aya-log records and log them using the default logger
|
|
|
-//! EbpfLogger::init(&mut bpf).unwrap();
|
|
|
+//! let logger = EbpfLogger::init(&mut bpf).unwrap();
|
|
|
+//! let mut logger = tokio::io::unix::AsyncFd::with_interest(logger, tokio::io::Interest::READABLE).unwrap();
|
|
|
+//! tokio::task::spawn(async move {
|
|
|
+//! loop {
|
|
|
+//! let mut guard = logger.readable_mut().await.unwrap();
|
|
|
+//! guard.get_inner_mut().flush();
|
|
|
+//! guard.clear_ready();
|
|
|
+//! }
|
|
|
+//! });
|
|
|
//! ```
|
|
|
//!
|
|
|
//! With the following eBPF code:
|
|
@@ -51,8 +59,9 @@
|
|
|
//!
|
|
|
use std::{
|
|
|
fmt::{LowerHex, UpperHex},
|
|
|
- io, mem,
|
|
|
+ mem,
|
|
|
net::{Ipv4Addr, Ipv6Addr},
|
|
|
+ os::fd::AsRawFd,
|
|
|
ptr, str,
|
|
|
};
|
|
|
|
|
@@ -84,45 +93,54 @@ unsafe impl Pod for DisplayHintWrapper {}
|
|
|
/// Log messages generated by `aya_log_ebpf` using the [log] crate.
|
|
|
///
|
|
|
/// For more details see the [module level documentation](crate).
|
|
|
-pub struct EbpfLogger;
|
|
|
+pub struct EbpfLogger<T> {
|
|
|
+ ring_buf: RingBuf<MapData>,
|
|
|
+ logger: T,
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> AsRawFd for EbpfLogger<T> {
|
|
|
+ fn as_raw_fd(&self) -> std::os::unix::prelude::RawFd {
|
|
|
+ let Self {
|
|
|
+ ring_buf,
|
|
|
+ logger: _,
|
|
|
+ } = self;
|
|
|
+ ring_buf.as_raw_fd()
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
/// Log messages generated by `aya_log_ebpf` using the [log] crate.
|
|
|
#[deprecated(since = "0.2.1", note = "Use `aya_log::EbpfLogger` instead")]
|
|
|
-pub type BpfLogger = EbpfLogger;
|
|
|
+pub type BpfLogger<T> = EbpfLogger<T>;
|
|
|
|
|
|
-impl EbpfLogger {
|
|
|
+impl EbpfLogger<&'static dyn Log> {
|
|
|
/// Starts reading log records created with `aya-log-ebpf` and logs them
|
|
|
/// with the default logger. See [log::logger].
|
|
|
- pub fn init(bpf: &mut Ebpf) -> Result<EbpfLogger, Error> {
|
|
|
- EbpfLogger::init_with_logger(bpf, log::logger())
|
|
|
- }
|
|
|
-
|
|
|
- /// Starts reading log records created with `aya-log-ebpf` and logs them
|
|
|
- /// with the given logger.
|
|
|
- pub fn init_with_logger<T: Log + 'static>(
|
|
|
- bpf: &mut Ebpf,
|
|
|
- logger: T,
|
|
|
- ) -> Result<EbpfLogger, Error> {
|
|
|
- let map = bpf.take_map(MAP_NAME).ok_or(Error::MapNotFound)?;
|
|
|
- Self::read_logs_async(map, logger)
|
|
|
+ pub fn init(bpf: &mut Ebpf) -> Result<Self, Error> {
|
|
|
+ Self::init_with_logger(bpf, log::logger())
|
|
|
}
|
|
|
|
|
|
/// Attaches to an existing `aya-log-ebpf` instance.
|
|
|
///
|
|
|
/// Attaches to the logs produced by `program_id`. Can be used to read logs generated by a
|
|
|
/// pinned program. The log records will be written to the default logger. See [log::logger].
|
|
|
- pub fn init_from_id(program_id: u32) -> Result<EbpfLogger, Error> {
|
|
|
+ pub fn init_from_id(program_id: u32) -> Result<Self, Error> {
|
|
|
Self::init_from_id_with_logger(program_id, log::logger())
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+impl<T: Log> EbpfLogger<T> {
|
|
|
+ /// Starts reading log records created with `aya-log-ebpf` and logs them
|
|
|
+ /// with the given logger.
|
|
|
+ pub fn init_with_logger(bpf: &mut Ebpf, logger: T) -> Result<Self, Error> {
|
|
|
+ let map = bpf.take_map(MAP_NAME).ok_or(Error::MapNotFound)?;
|
|
|
+ Self::new(map, logger)
|
|
|
+ }
|
|
|
|
|
|
/// Attaches to an existing `aya-log-ebpf` instance and logs with the given logger.
|
|
|
///
|
|
|
/// Attaches to the logs produced by `program_id`. Can be used to read logs generated by a
|
|
|
/// pinned program. The log records will be written to the given logger.
|
|
|
- pub fn init_from_id_with_logger<T: Log + 'static>(
|
|
|
- program_id: u32,
|
|
|
- logger: T,
|
|
|
- ) -> Result<EbpfLogger, Error> {
|
|
|
+ pub fn init_from_id_with_logger(program_id: u32, logger: T) -> Result<Self, Error> {
|
|
|
let program_info = loaded_programs()
|
|
|
.filter_map(|info| info.ok())
|
|
|
.find(|info| info.id() == program_id)
|
|
@@ -140,26 +158,21 @@ impl EbpfLogger {
|
|
|
.ok_or(Error::MapNotFound)?;
|
|
|
let map = MapData::from_id(map.id())?;
|
|
|
|
|
|
- Self::read_logs_async(Map::RingBuf(map), logger)
|
|
|
+ Self::new(Map::RingBuf(map), logger)
|
|
|
}
|
|
|
|
|
|
- fn read_logs_async<T: Log + 'static>(map: Map, logger: T) -> Result<Self, Error> {
|
|
|
+ fn new(map: Map, logger: T) -> Result<Self, Error> {
|
|
|
let ring_buf: RingBuf<_> = map.try_into()?;
|
|
|
- let mut async_fd =
|
|
|
- tokio::io::unix::AsyncFd::with_interest(ring_buf, tokio::io::Interest::READABLE)
|
|
|
- .map_err(Error::AsyncFdNew)?;
|
|
|
-
|
|
|
- tokio::spawn(async move {
|
|
|
- loop {
|
|
|
- let mut guard = async_fd.readable_mut().await.unwrap();
|
|
|
- while let Some(buf) = guard.get_inner_mut().next() {
|
|
|
- log_buf(buf.as_ref(), &logger).unwrap();
|
|
|
- }
|
|
|
- guard.clear_ready();
|
|
|
- }
|
|
|
- });
|
|
|
|
|
|
- Ok(EbpfLogger {})
|
|
|
+ Ok(EbpfLogger { ring_buf, logger })
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Reads log records from eBPF and writes them to the logger.
|
|
|
+ pub fn flush(&mut self) {
|
|
|
+ let Self { ring_buf, logger } = self;
|
|
|
+ while let Some(buf) = ring_buf.next() {
|
|
|
+ log_buf(buf.as_ref(), logger).unwrap();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -429,9 +442,6 @@ pub enum Error {
|
|
|
#[error(transparent)]
|
|
|
MapError(#[from] MapError),
|
|
|
|
|
|
- #[error("tokio::io::unix::AsyncFd::new")]
|
|
|
- AsyncFdNew(#[source] io::Error),
|
|
|
-
|
|
|
#[error("program not found")]
|
|
|
ProgramNotFound,
|
|
|
|