diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index e24acfb4..8c89c115 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -60,10 +60,12 @@ use std::{ const MAP_NAME: &str = "AYA_LOGS"; use aya::{ + loaded_programs, maps::{ perf::{AsyncPerfEventArray, Events, PerfBufferError}, - MapError, + Map, MapData, MapError, MapInfo, }, + programs::ProgramError, util::online_cpus, Ebpf, Pod, }; @@ -112,12 +114,52 @@ impl EbpfLogger { bpf: &mut Ebpf, logger: T, ) -> Result { - let logger = Arc::new(logger); - let mut logs: AsyncPerfEventArray<_> = bpf - .take_map(MAP_NAME) - .ok_or(Error::MapNotFound)? - .try_into()?; + let map = bpf.take_map(MAP_NAME).ok_or(Error::MapNotFound)?; + Self::read_logs_async(map, logger)?; + Ok(EbpfLogger {}) + } + + /// 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 { + Self::init_from_id_with_logger(program_id, log::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( + program_id: u32, + logger: T, + ) -> Result { + let program_info = loaded_programs() + .filter_map(|info| info.ok()) + .find(|info| info.id() == program_id) + .ok_or(Error::ProgramNotFound)?; + let map = program_info + .map_ids() + .map_err(Error::ProgramError)? + .iter() + .filter_map(|id| MapInfo::from_id(*id).ok()) + .find(|map_info| match map_info.name_as_str() { + Some(name) => name == MAP_NAME, + None => false, + }) + .ok_or(Error::MapNotFound)?; + let map = MapData::from_id(map.id()).map_err(Error::MapError)?; + + Self::read_logs_async(Map::PerfEventArray(map), logger)?; + + Ok(EbpfLogger {}) + } + + fn read_logs_async(map: Map, logger: T) -> Result<(), Error> { + let mut logs: AsyncPerfEventArray<_> = map.try_into()?; + + let logger = Arc::new(logger); for cpu_id in online_cpus().map_err(Error::InvalidOnlineCpu)? { let mut buf = logs.open(cpu_id, None)?; @@ -134,8 +176,7 @@ impl EbpfLogger { } }); } - - Ok(EbpfLogger {}) + Ok(()) } } @@ -374,6 +415,12 @@ pub enum Error { #[error("invalid /sys/devices/system/cpu/online format")] InvalidOnlineCpu(#[source] io::Error), + + #[error("program not found")] + ProgramNotFound, + + #[error(transparent)] + ProgramError(#[from] ProgramError), } fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> { diff --git a/xtask/public-api/aya-log.txt b/xtask/public-api/aya-log.txt index 843f436b..8c04980e 100644 --- a/xtask/public-api/aya-log.txt +++ b/xtask/public-api/aya-log.txt @@ -4,10 +4,14 @@ pub aya_log::Error::InvalidOnlineCpu(std::io::error::Error) pub aya_log::Error::MapError(aya::maps::MapError) pub aya_log::Error::MapNotFound pub aya_log::Error::PerfBufferError(aya::maps::perf::perf_buffer::PerfBufferError) +pub aya_log::Error::ProgramError(aya::programs::ProgramError) +pub aya_log::Error::ProgramNotFound impl core::convert::From for aya_log::Error pub fn aya_log::Error::from(source: aya::maps::MapError) -> Self impl core::convert::From for aya_log::Error pub fn aya_log::Error::from(source: aya::maps::perf::perf_buffer::PerfBufferError) -> Self +impl core::convert::From for aya_log::Error +pub fn aya_log::Error::from(source: aya::programs::ProgramError) -> Self impl core::error::Error for aya_log::Error pub fn aya_log::Error::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> impl core::fmt::Debug for aya_log::Error @@ -66,6 +70,8 @@ pub fn aya_log::DefaultFormatter::from(t: T) -> T pub struct aya_log::EbpfLogger impl aya_log::EbpfLogger pub fn aya_log::EbpfLogger::init(bpf: &mut aya::bpf::Ebpf) -> core::result::Result +pub fn aya_log::EbpfLogger::init_from_id(program_id: u32) -> core::result::Result +pub fn aya_log::EbpfLogger::init_from_id_with_logger(program_id: u32, logger: T) -> core::result::Result pub fn aya_log::EbpfLogger::init_with_logger(bpf: &mut aya::bpf::Ebpf, logger: T) -> core::result::Result impl core::marker::Freeze for aya_log::EbpfLogger impl core::marker::Send for aya_log::EbpfLogger