lib.rs 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  1. //! A logging framework for eBPF programs.
  2. //!
  3. //! This is the user space side of the [Aya] logging framework. For the eBPF
  4. //! side, see the `aya-log-ebpf` crate.
  5. //!
  6. //! `aya-log` provides the [EbpfLogger] type, which reads log records created by
  7. //! `aya-log-ebpf` and logs them using the [log] crate. Any logger that
  8. //! implements the [Log] trait can be used with this crate.
  9. //!
  10. //! # Example:
  11. //!
  12. //! This example uses the [env_logger] crate to log messages to the terminal.
  13. //!
  14. //! ```no_run
  15. //! # let mut bpf = aya::Ebpf::load(&[]).unwrap();
  16. //! use aya_log::EbpfLogger;
  17. //!
  18. //! // initialize env_logger as the default logger
  19. //! env_logger::init();
  20. //!
  21. //! // start reading aya-log records and log them using the default logger
  22. //! EbpfLogger::init(&mut bpf).unwrap();
  23. //! ```
  24. //!
  25. //! With the following eBPF code:
  26. //!
  27. //! ```ignore
  28. //! # let ctx = ();
  29. //! use aya_log_ebpf::{debug, error, info, trace, warn};
  30. //!
  31. //! error!(&ctx, "this is an error message 🚨");
  32. //! warn!(&ctx, "this is a warning message ⚠️");
  33. //! info!(&ctx, "this is an info message ℹ️");
  34. //! debug!(&ctx, "this is a debug message ️🐝");
  35. //! trace!(&ctx, "this is a trace message 🔍");
  36. //! ```
  37. //! Outputs:
  38. //!
  39. //! ```text
  40. //! 21:58:55 [ERROR] xxx: [src/main.rs:35] this is an error message 🚨
  41. //! 21:58:55 [WARN] xxx: [src/main.rs:36] this is a warning message ⚠️
  42. //! 21:58:55 [INFO] xxx: [src/main.rs:37] this is an info message ℹ️
  43. //! 21:58:55 [DEBUG] (7) xxx: [src/main.rs:38] this is a debug message ️🐝
  44. //! 21:58:55 [TRACE] (7) xxx: [src/main.rs:39] this is a trace message 🔍
  45. //! ```
  46. //!
  47. //! [Aya]: https://docs.rs/aya
  48. //! [env_logger]: https://docs.rs/env_logger
  49. //! [Log]: https://docs.rs/log/0.4.14/log/trait.Log.html
  50. //! [log]: https://docs.rs/log
  51. //!
  52. use std::{
  53. fmt::{LowerHex, UpperHex},
  54. io, mem,
  55. net::{Ipv4Addr, Ipv6Addr},
  56. ptr, str,
  57. sync::Arc,
  58. };
  59. const MAP_NAME: &str = "AYA_LOGS";
  60. use aya::{
  61. Ebpf, Pod,
  62. maps::{
  63. Map, MapData, MapError, MapInfo,
  64. perf::{AsyncPerfEventArray, Events, PerfBufferError},
  65. },
  66. programs::{ProgramError, loaded_programs},
  67. util::online_cpus,
  68. };
  69. use aya_log_common::{
  70. Argument, DisplayHint, LOG_BUF_CAPACITY, LOG_FIELDS, Level, LogValueLength, RecordField,
  71. };
  72. use bytes::BytesMut;
  73. use log::{Log, Record, error};
  74. use thiserror::Error;
  75. #[expect(dead_code)] // TODO(https://github.com/rust-lang/rust/issues/120770): Remove when false positive is fixed.
  76. #[derive(Copy, Clone)]
  77. #[repr(transparent)]
  78. struct RecordFieldWrapper(RecordField);
  79. #[expect(dead_code)] // TODO(https://github.com/rust-lang/rust/issues/120770): Remove when false positive is fixed.
  80. #[derive(Copy, Clone)]
  81. #[repr(transparent)]
  82. struct ArgumentWrapper(Argument);
  83. #[derive(Copy, Clone)]
  84. #[repr(transparent)]
  85. struct DisplayHintWrapper(DisplayHint);
  86. unsafe impl Pod for RecordFieldWrapper {}
  87. unsafe impl Pod for ArgumentWrapper {}
  88. unsafe impl Pod for DisplayHintWrapper {}
  89. /// Log messages generated by `aya_log_ebpf` using the [log] crate.
  90. ///
  91. /// For more details see the [module level documentation](crate).
  92. pub struct EbpfLogger;
  93. /// Log messages generated by `aya_log_ebpf` using the [log] crate.
  94. #[deprecated(since = "0.2.1", note = "Use `aya_log::EbpfLogger` instead")]
  95. pub type BpfLogger = EbpfLogger;
  96. impl EbpfLogger {
  97. /// Starts reading log records created with `aya-log-ebpf` and logs them
  98. /// with the default logger. See [log::logger].
  99. pub fn init(bpf: &mut Ebpf) -> Result<EbpfLogger, Error> {
  100. EbpfLogger::init_with_logger(bpf, log::logger())
  101. }
  102. /// Starts reading log records created with `aya-log-ebpf` and logs them
  103. /// with the given logger.
  104. pub fn init_with_logger<T: Log + 'static>(
  105. bpf: &mut Ebpf,
  106. logger: T,
  107. ) -> Result<EbpfLogger, Error> {
  108. let map = bpf.take_map(MAP_NAME).ok_or(Error::MapNotFound)?;
  109. Self::read_logs_async(map, logger)?;
  110. Ok(EbpfLogger {})
  111. }
  112. /// Attaches to an existing `aya-log-ebpf` instance.
  113. ///
  114. /// Attaches to the logs produced by `program_id`. Can be used to read logs generated by a
  115. /// pinned program. The log records will be written to the default logger. See [log::logger].
  116. pub fn init_from_id(program_id: u32) -> Result<EbpfLogger, Error> {
  117. Self::init_from_id_with_logger(program_id, log::logger())
  118. }
  119. /// Attaches to an existing `aya-log-ebpf` instance and logs with the given logger.
  120. ///
  121. /// Attaches to the logs produced by `program_id`. Can be used to read logs generated by a
  122. /// pinned program. The log records will be written to the given logger.
  123. pub fn init_from_id_with_logger<T: Log + 'static>(
  124. program_id: u32,
  125. logger: T,
  126. ) -> Result<EbpfLogger, Error> {
  127. let program_info = loaded_programs()
  128. .filter_map(|info| info.ok())
  129. .find(|info| info.id() == program_id)
  130. .ok_or(Error::ProgramNotFound)?;
  131. let map = program_info
  132. .map_ids()
  133. .map_err(Error::ProgramError)?
  134. .ok_or_else(|| Error::MapNotFound)?
  135. .iter()
  136. .filter_map(|id| MapInfo::from_id(*id).ok())
  137. .find(|map_info| match map_info.name_as_str() {
  138. Some(name) => name == MAP_NAME,
  139. None => false,
  140. })
  141. .ok_or(Error::MapNotFound)?;
  142. let map = MapData::from_id(map.id()).map_err(Error::MapError)?;
  143. Self::read_logs_async(Map::PerfEventArray(map), logger)?;
  144. Ok(EbpfLogger {})
  145. }
  146. fn read_logs_async<T: Log + 'static>(map: Map, logger: T) -> Result<(), Error> {
  147. let mut logs: AsyncPerfEventArray<_> = map.try_into()?;
  148. let logger = Arc::new(logger);
  149. for cpu_id in online_cpus().map_err(|(_, error)| Error::InvalidOnlineCpu(error))? {
  150. let mut buf = logs.open(cpu_id, None)?;
  151. let log = logger.clone();
  152. tokio::spawn(async move {
  153. let mut buffers = vec![BytesMut::with_capacity(LOG_BUF_CAPACITY); 10];
  154. loop {
  155. let Events { read, lost: _ } = buf.read_events(&mut buffers).await.unwrap();
  156. for buf in buffers.iter().take(read) {
  157. log_buf(buf.as_ref(), &*log).unwrap();
  158. }
  159. }
  160. });
  161. }
  162. Ok(())
  163. }
  164. }
  165. pub trait Formatter<T> {
  166. fn format(v: T) -> String;
  167. }
  168. pub struct DefaultFormatter;
  169. impl<T> Formatter<T> for DefaultFormatter
  170. where
  171. T: ToString,
  172. {
  173. fn format(v: T) -> String {
  174. v.to_string()
  175. }
  176. }
  177. pub struct LowerHexFormatter;
  178. impl<T> Formatter<T> for LowerHexFormatter
  179. where
  180. T: LowerHex,
  181. {
  182. fn format(v: T) -> String {
  183. format!("{v:x}")
  184. }
  185. }
  186. pub struct LowerHexBytesFormatter;
  187. impl Formatter<&[u8]> for LowerHexBytesFormatter {
  188. fn format(v: &[u8]) -> String {
  189. let mut s = String::new();
  190. for v in v {
  191. let () = core::fmt::write(&mut s, format_args!("{v:02x}")).unwrap();
  192. }
  193. s
  194. }
  195. }
  196. pub struct UpperHexFormatter;
  197. impl<T> Formatter<T> for UpperHexFormatter
  198. where
  199. T: UpperHex,
  200. {
  201. fn format(v: T) -> String {
  202. format!("{v:X}")
  203. }
  204. }
  205. pub struct UpperHexBytesFormatter;
  206. impl Formatter<&[u8]> for UpperHexBytesFormatter {
  207. fn format(v: &[u8]) -> String {
  208. let mut s = String::new();
  209. for v in v {
  210. let () = core::fmt::write(&mut s, format_args!("{v:02X}")).unwrap();
  211. }
  212. s
  213. }
  214. }
  215. pub struct Ipv4Formatter;
  216. impl<T> Formatter<T> for Ipv4Formatter
  217. where
  218. T: Into<Ipv4Addr>,
  219. {
  220. fn format(v: T) -> String {
  221. v.into().to_string()
  222. }
  223. }
  224. pub struct Ipv6Formatter;
  225. impl<T> Formatter<T> for Ipv6Formatter
  226. where
  227. T: Into<Ipv6Addr>,
  228. {
  229. fn format(v: T) -> String {
  230. v.into().to_string()
  231. }
  232. }
  233. pub struct LowerMacFormatter;
  234. impl Formatter<[u8; 6]> for LowerMacFormatter {
  235. fn format(v: [u8; 6]) -> String {
  236. format!(
  237. "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
  238. v[0], v[1], v[2], v[3], v[4], v[5]
  239. )
  240. }
  241. }
  242. pub struct UpperMacFormatter;
  243. impl Formatter<[u8; 6]> for UpperMacFormatter {
  244. fn format(v: [u8; 6]) -> String {
  245. format!(
  246. "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
  247. v[0], v[1], v[2], v[3], v[4], v[5]
  248. )
  249. }
  250. }
  251. trait Format {
  252. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()>;
  253. }
  254. impl Format for &[u8] {
  255. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  256. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  257. Some(DisplayHint::LowerHex) => Ok(LowerHexBytesFormatter::format(self)),
  258. Some(DisplayHint::UpperHex) => Ok(UpperHexBytesFormatter::format(self)),
  259. _ => Err(()),
  260. }
  261. }
  262. }
  263. impl Format for u32 {
  264. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  265. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  266. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  267. Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
  268. Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
  269. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  270. Some(DisplayHint::LowerMac) => Err(()),
  271. Some(DisplayHint::UpperMac) => Err(()),
  272. _ => Ok(DefaultFormatter::format(self)),
  273. }
  274. }
  275. }
  276. impl Format for Ipv4Addr {
  277. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  278. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  279. Some(DisplayHint::Default) => Ok(Ipv4Formatter::format(*self)),
  280. Some(DisplayHint::LowerHex) => Err(()),
  281. Some(DisplayHint::UpperHex) => Err(()),
  282. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  283. Some(DisplayHint::LowerMac) => Err(()),
  284. Some(DisplayHint::UpperMac) => Err(()),
  285. None => Ok(Ipv4Formatter::format(*self)),
  286. }
  287. }
  288. }
  289. impl Format for Ipv6Addr {
  290. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  291. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  292. Some(DisplayHint::Default) => Ok(Ipv6Formatter::format(*self)),
  293. Some(DisplayHint::LowerHex) => Err(()),
  294. Some(DisplayHint::UpperHex) => Err(()),
  295. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  296. Some(DisplayHint::LowerMac) => Err(()),
  297. Some(DisplayHint::UpperMac) => Err(()),
  298. None => Ok(Ipv6Formatter::format(*self)),
  299. }
  300. }
  301. }
  302. impl Format for [u8; 4] {
  303. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  304. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  305. Some(DisplayHint::Default) => Ok(Ipv4Formatter::format(*self)),
  306. Some(DisplayHint::LowerHex) => Err(()),
  307. Some(DisplayHint::UpperHex) => Err(()),
  308. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  309. Some(DisplayHint::LowerMac) => Err(()),
  310. Some(DisplayHint::UpperMac) => Err(()),
  311. None => Ok(Ipv4Formatter::format(*self)),
  312. }
  313. }
  314. }
  315. impl Format for [u8; 6] {
  316. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  317. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  318. Some(DisplayHint::Default) => Err(()),
  319. Some(DisplayHint::LowerHex) => Err(()),
  320. Some(DisplayHint::UpperHex) => Err(()),
  321. Some(DisplayHint::Ip) => Err(()),
  322. Some(DisplayHint::LowerMac) => Ok(LowerMacFormatter::format(*self)),
  323. Some(DisplayHint::UpperMac) => Ok(UpperMacFormatter::format(*self)),
  324. _ => Err(()),
  325. }
  326. }
  327. }
  328. impl Format for [u8; 16] {
  329. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  330. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  331. Some(DisplayHint::Default) => Err(()),
  332. Some(DisplayHint::LowerHex) => Err(()),
  333. Some(DisplayHint::UpperHex) => Err(()),
  334. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  335. Some(DisplayHint::LowerMac) => Err(()),
  336. Some(DisplayHint::UpperMac) => Err(()),
  337. _ => Err(()),
  338. }
  339. }
  340. }
  341. impl Format for [u16; 8] {
  342. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  343. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  344. Some(DisplayHint::Default) => Err(()),
  345. Some(DisplayHint::LowerHex) => Err(()),
  346. Some(DisplayHint::UpperHex) => Err(()),
  347. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  348. Some(DisplayHint::LowerMac) => Err(()),
  349. Some(DisplayHint::UpperMac) => Err(()),
  350. _ => Err(()),
  351. }
  352. }
  353. }
  354. macro_rules! impl_format {
  355. ($type:ident) => {
  356. impl Format for $type {
  357. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  358. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  359. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  360. Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
  361. Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
  362. Some(DisplayHint::Ip) => Err(()),
  363. Some(DisplayHint::LowerMac) => Err(()),
  364. Some(DisplayHint::UpperMac) => Err(()),
  365. _ => Ok(DefaultFormatter::format(self)),
  366. }
  367. }
  368. }
  369. };
  370. }
  371. impl_format!(i8);
  372. impl_format!(i16);
  373. impl_format!(i32);
  374. impl_format!(i64);
  375. impl_format!(isize);
  376. impl_format!(u8);
  377. impl_format!(u16);
  378. impl_format!(u64);
  379. impl_format!(usize);
  380. macro_rules! impl_format_float {
  381. ($type:ident) => {
  382. impl Format for $type {
  383. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  384. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  385. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  386. Some(DisplayHint::LowerHex) => Err(()),
  387. Some(DisplayHint::UpperHex) => Err(()),
  388. Some(DisplayHint::Ip) => Err(()),
  389. Some(DisplayHint::LowerMac) => Err(()),
  390. Some(DisplayHint::UpperMac) => Err(()),
  391. _ => Ok(DefaultFormatter::format(self)),
  392. }
  393. }
  394. }
  395. };
  396. }
  397. impl_format_float!(f32);
  398. impl_format_float!(f64);
  399. #[derive(Error, Debug)]
  400. pub enum Error {
  401. #[error("log event array {} doesn't exist", MAP_NAME)]
  402. MapNotFound,
  403. #[error("error opening log event array")]
  404. MapError(#[from] MapError),
  405. #[error("error opening log buffer")]
  406. PerfBufferError(#[from] PerfBufferError),
  407. #[error("invalid /sys/devices/system/cpu/online format")]
  408. InvalidOnlineCpu(#[source] io::Error),
  409. #[error("program not found")]
  410. ProgramNotFound,
  411. #[error(transparent)]
  412. ProgramError(#[from] ProgramError),
  413. }
  414. fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
  415. let mut target = None;
  416. let mut level = None;
  417. let mut module = None;
  418. let mut file = None;
  419. let mut line = None;
  420. let mut num_args = None;
  421. for () in std::iter::repeat_n((), LOG_FIELDS) {
  422. let (RecordFieldWrapper(tag), value, rest) = try_read(buf)?;
  423. match tag {
  424. RecordField::Target => {
  425. target = Some(str::from_utf8(value).map_err(|std::str::Utf8Error { .. }| ())?);
  426. }
  427. RecordField::Level => {
  428. level = Some({
  429. let level = unsafe { ptr::read_unaligned(value.as_ptr() as *const _) };
  430. match level {
  431. Level::Error => log::Level::Error,
  432. Level::Warn => log::Level::Warn,
  433. Level::Info => log::Level::Info,
  434. Level::Debug => log::Level::Debug,
  435. Level::Trace => log::Level::Trace,
  436. }
  437. })
  438. }
  439. RecordField::Module => {
  440. module = Some(str::from_utf8(value).map_err(|std::str::Utf8Error { .. }| ())?);
  441. }
  442. RecordField::File => {
  443. file = Some(str::from_utf8(value).map_err(|std::str::Utf8Error { .. }| ())?);
  444. }
  445. RecordField::Line => {
  446. line = Some(u32::from_ne_bytes(
  447. value
  448. .try_into()
  449. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  450. ));
  451. }
  452. RecordField::NumArgs => {
  453. num_args = Some(usize::from_ne_bytes(
  454. value
  455. .try_into()
  456. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  457. ));
  458. }
  459. }
  460. buf = rest;
  461. }
  462. let mut full_log_msg = String::new();
  463. let mut last_hint: Option<DisplayHintWrapper> = None;
  464. for () in std::iter::repeat_n((), num_args.ok_or(())?) {
  465. let (ArgumentWrapper(tag), value, rest) = try_read(buf)?;
  466. match tag {
  467. Argument::DisplayHint => {
  468. last_hint = Some(unsafe { ptr::read_unaligned(value.as_ptr() as *const _) });
  469. }
  470. Argument::I8 => {
  471. full_log_msg.push_str(
  472. &i8::from_ne_bytes(
  473. value
  474. .try_into()
  475. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  476. )
  477. .format(last_hint.take())?,
  478. );
  479. }
  480. Argument::I16 => {
  481. full_log_msg.push_str(
  482. &i16::from_ne_bytes(
  483. value
  484. .try_into()
  485. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  486. )
  487. .format(last_hint.take())?,
  488. );
  489. }
  490. Argument::I32 => {
  491. full_log_msg.push_str(
  492. &i32::from_ne_bytes(
  493. value
  494. .try_into()
  495. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  496. )
  497. .format(last_hint.take())?,
  498. );
  499. }
  500. Argument::I64 => {
  501. full_log_msg.push_str(
  502. &i64::from_ne_bytes(
  503. value
  504. .try_into()
  505. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  506. )
  507. .format(last_hint.take())?,
  508. );
  509. }
  510. Argument::Isize => {
  511. full_log_msg.push_str(
  512. &isize::from_ne_bytes(
  513. value
  514. .try_into()
  515. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  516. )
  517. .format(last_hint.take())?,
  518. );
  519. }
  520. Argument::U8 => {
  521. full_log_msg.push_str(
  522. &u8::from_ne_bytes(
  523. value
  524. .try_into()
  525. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  526. )
  527. .format(last_hint.take())?,
  528. );
  529. }
  530. Argument::U16 => {
  531. full_log_msg.push_str(
  532. &u16::from_ne_bytes(
  533. value
  534. .try_into()
  535. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  536. )
  537. .format(last_hint.take())?,
  538. );
  539. }
  540. Argument::U32 => {
  541. full_log_msg.push_str(
  542. &u32::from_ne_bytes(
  543. value
  544. .try_into()
  545. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  546. )
  547. .format(last_hint.take())?,
  548. );
  549. }
  550. Argument::U64 => {
  551. full_log_msg.push_str(
  552. &u64::from_ne_bytes(
  553. value
  554. .try_into()
  555. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  556. )
  557. .format(last_hint.take())?,
  558. );
  559. }
  560. Argument::Usize => {
  561. full_log_msg.push_str(
  562. &usize::from_ne_bytes(
  563. value
  564. .try_into()
  565. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  566. )
  567. .format(last_hint.take())?,
  568. );
  569. }
  570. Argument::F32 => {
  571. full_log_msg.push_str(
  572. &f32::from_ne_bytes(
  573. value
  574. .try_into()
  575. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  576. )
  577. .format(last_hint.take())?,
  578. );
  579. }
  580. Argument::F64 => {
  581. full_log_msg.push_str(
  582. &f64::from_ne_bytes(
  583. value
  584. .try_into()
  585. .map_err(|std::array::TryFromSliceError { .. }| ())?,
  586. )
  587. .format(last_hint.take())?,
  588. );
  589. }
  590. Argument::Ipv4Addr => {
  591. let value: [u8; 4] = value
  592. .try_into()
  593. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  594. let value = Ipv4Addr::from(value);
  595. full_log_msg.push_str(&value.format(last_hint.take())?)
  596. }
  597. Argument::Ipv6Addr => {
  598. let value: [u8; 16] = value
  599. .try_into()
  600. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  601. let value = Ipv6Addr::from(value);
  602. full_log_msg.push_str(&value.format(last_hint.take())?)
  603. }
  604. Argument::ArrU8Len4 => {
  605. let value: [u8; 4] = value
  606. .try_into()
  607. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  608. full_log_msg.push_str(&value.format(last_hint.take())?);
  609. }
  610. Argument::ArrU8Len6 => {
  611. let value: [u8; 6] = value
  612. .try_into()
  613. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  614. full_log_msg.push_str(&value.format(last_hint.take())?);
  615. }
  616. Argument::ArrU8Len16 => {
  617. let value: [u8; 16] = value
  618. .try_into()
  619. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  620. full_log_msg.push_str(&value.format(last_hint.take())?);
  621. }
  622. Argument::ArrU16Len8 => {
  623. let data: [u8; 16] = value
  624. .try_into()
  625. .map_err(|std::array::TryFromSliceError { .. }| ())?;
  626. let mut value: [u16; 8] = Default::default();
  627. for (i, s) in data.chunks_exact(2).enumerate() {
  628. value[i] = ((s[1] as u16) << 8) | s[0] as u16;
  629. }
  630. full_log_msg.push_str(&value.format(last_hint.take())?);
  631. }
  632. Argument::Bytes => {
  633. full_log_msg.push_str(&value.format(last_hint.take())?);
  634. }
  635. Argument::Str => match str::from_utf8(value) {
  636. Ok(v) => {
  637. full_log_msg.push_str(v);
  638. }
  639. Err(e) => error!("received invalid utf8 string: {e}"),
  640. },
  641. }
  642. buf = rest;
  643. }
  644. logger.log(
  645. &Record::builder()
  646. .args(format_args!("{full_log_msg}"))
  647. .target(target.ok_or(())?)
  648. .level(level.ok_or(())?)
  649. .module_path(module)
  650. .file(file)
  651. .line(line)
  652. .build(),
  653. );
  654. logger.flush();
  655. Ok(())
  656. }
  657. fn try_read<T: Pod>(mut buf: &[u8]) -> Result<(T, &[u8], &[u8]), ()> {
  658. if buf.len() < mem::size_of::<T>() + mem::size_of::<LogValueLength>() {
  659. return Err(());
  660. }
  661. let tag = unsafe { ptr::read_unaligned(buf.as_ptr() as *const T) };
  662. buf = &buf[mem::size_of::<T>()..];
  663. let len =
  664. LogValueLength::from_ne_bytes(buf[..mem::size_of::<LogValueLength>()].try_into().unwrap());
  665. buf = &buf[mem::size_of::<LogValueLength>()..];
  666. let len: usize = len.into();
  667. if buf.len() < len {
  668. return Err(());
  669. }
  670. let (value, rest) = buf.split_at(len);
  671. Ok((tag, value, rest))
  672. }
  673. #[cfg(test)]
  674. mod test {
  675. use std::net::IpAddr;
  676. use aya_log_common::{WriteToBuf as _, write_record_header};
  677. use log::{Level, logger};
  678. use super::*;
  679. fn new_log(args: usize) -> Option<(usize, Vec<u8>)> {
  680. let mut buf = vec![0; 8192];
  681. let len = write_record_header(
  682. &mut buf,
  683. "test",
  684. aya_log_common::Level::Info,
  685. "test",
  686. "test.rs",
  687. 123,
  688. args,
  689. )?;
  690. Some((len.get(), buf))
  691. }
  692. #[test]
  693. fn test_str() {
  694. testing_logger::setup();
  695. let (mut len, mut input) = new_log(1).unwrap();
  696. len += "test".write(&mut input[len..]).unwrap().get();
  697. _ = len;
  698. let logger = logger();
  699. let () = log_buf(&input, logger).unwrap();
  700. testing_logger::validate(|captured_logs| {
  701. assert_eq!(captured_logs.len(), 1);
  702. assert_eq!(captured_logs[0].body, "test");
  703. assert_eq!(captured_logs[0].level, Level::Info);
  704. });
  705. }
  706. #[test]
  707. fn test_str_with_args() {
  708. testing_logger::setup();
  709. let (mut len, mut input) = new_log(2).unwrap();
  710. len += "hello ".write(&mut input[len..]).unwrap().get();
  711. len += "test".write(&mut input[len..]).unwrap().get();
  712. _ = len;
  713. let logger = logger();
  714. let () = log_buf(&input, logger).unwrap();
  715. testing_logger::validate(|captured_logs| {
  716. assert_eq!(captured_logs.len(), 1);
  717. assert_eq!(captured_logs[0].body, "hello test");
  718. assert_eq!(captured_logs[0].level, Level::Info);
  719. });
  720. }
  721. #[test]
  722. fn test_bytes() {
  723. testing_logger::setup();
  724. let (mut len, mut input) = new_log(2).unwrap();
  725. len += DisplayHint::LowerHex
  726. .write(&mut input[len..])
  727. .unwrap()
  728. .get();
  729. len += [0xde, 0xad].write(&mut input[len..]).unwrap().get();
  730. _ = len;
  731. let logger = logger();
  732. let () = log_buf(&input, logger).unwrap();
  733. testing_logger::validate(|captured_logs| {
  734. assert_eq!(captured_logs.len(), 1);
  735. assert_eq!(captured_logs[0].body, "dead");
  736. assert_eq!(captured_logs[0].level, Level::Info);
  737. });
  738. }
  739. #[test]
  740. fn test_bytes_with_args() {
  741. testing_logger::setup();
  742. let (mut len, mut input) = new_log(5).unwrap();
  743. len += DisplayHint::LowerHex
  744. .write(&mut input[len..])
  745. .unwrap()
  746. .get();
  747. len += [0xde, 0xad].write(&mut input[len..]).unwrap().get();
  748. len += " ".write(&mut input[len..]).unwrap().get();
  749. len += DisplayHint::UpperHex
  750. .write(&mut input[len..])
  751. .unwrap()
  752. .get();
  753. len += [0xbe, 0xef].write(&mut input[len..]).unwrap().get();
  754. _ = len;
  755. let logger = logger();
  756. let () = log_buf(&input, logger).unwrap();
  757. testing_logger::validate(|captured_logs| {
  758. assert_eq!(captured_logs.len(), 1);
  759. assert_eq!(captured_logs[0].body, "dead BEEF");
  760. assert_eq!(captured_logs[0].level, Level::Info);
  761. });
  762. }
  763. #[test]
  764. fn test_bytes_unambiguous() {
  765. testing_logger::setup();
  766. let (mut len, mut input) = new_log(5).unwrap();
  767. len += DisplayHint::LowerHex
  768. .write(&mut input[len..])
  769. .unwrap()
  770. .get();
  771. len += [0x01, 0x02].write(&mut input[len..]).unwrap().get();
  772. len += " ".write(&mut input[len..]).unwrap().get();
  773. len += DisplayHint::LowerHex
  774. .write(&mut input[len..])
  775. .unwrap()
  776. .get();
  777. len += [0x12].write(&mut input[len..]).unwrap().get();
  778. _ = len;
  779. let logger = logger();
  780. let () = log_buf(&input, logger).unwrap();
  781. testing_logger::validate(|captured_logs| {
  782. assert_eq!(captured_logs.len(), 1);
  783. assert_eq!(captured_logs[0].body, "0102 12");
  784. assert_eq!(captured_logs[0].level, Level::Info);
  785. });
  786. }
  787. #[test]
  788. fn test_display_hint_default() {
  789. testing_logger::setup();
  790. let (mut len, mut input) = new_log(3).unwrap();
  791. len += "default hint: ".write(&mut input[len..]).unwrap().get();
  792. len += DisplayHint::Default.write(&mut input[len..]).unwrap().get();
  793. len += 14.write(&mut input[len..]).unwrap().get();
  794. _ = len;
  795. let logger = logger();
  796. let () = log_buf(&input, logger).unwrap();
  797. testing_logger::validate(|captured_logs| {
  798. assert_eq!(captured_logs.len(), 1);
  799. assert_eq!(captured_logs[0].body, "default hint: 14");
  800. assert_eq!(captured_logs[0].level, Level::Info);
  801. });
  802. }
  803. #[test]
  804. fn test_display_hint_lower_hex() {
  805. testing_logger::setup();
  806. let (mut len, mut input) = new_log(3).unwrap();
  807. len += "lower hex: ".write(&mut input[len..]).unwrap().get();
  808. len += DisplayHint::LowerHex
  809. .write(&mut input[len..])
  810. .unwrap()
  811. .get();
  812. len += 200.write(&mut input[len..]).unwrap().get();
  813. _ = len;
  814. let logger = logger();
  815. let () = log_buf(&input, logger).unwrap();
  816. testing_logger::validate(|captured_logs| {
  817. assert_eq!(captured_logs.len(), 1);
  818. assert_eq!(captured_logs[0].body, "lower hex: c8");
  819. assert_eq!(captured_logs[0].level, Level::Info);
  820. });
  821. }
  822. #[test]
  823. fn test_display_hint_upper_hex() {
  824. testing_logger::setup();
  825. let (mut len, mut input) = new_log(3).unwrap();
  826. len += "upper hex: ".write(&mut input[len..]).unwrap().get();
  827. len += DisplayHint::UpperHex
  828. .write(&mut input[len..])
  829. .unwrap()
  830. .get();
  831. len += 200.write(&mut input[len..]).unwrap().get();
  832. _ = len;
  833. let logger = logger();
  834. let () = log_buf(&input, logger).unwrap();
  835. testing_logger::validate(|captured_logs| {
  836. assert_eq!(captured_logs.len(), 1);
  837. assert_eq!(captured_logs[0].body, "upper hex: C8");
  838. assert_eq!(captured_logs[0].level, Level::Info);
  839. });
  840. }
  841. #[test]
  842. fn test_display_hint_ipv4() {
  843. testing_logger::setup();
  844. let (mut len, mut input) = new_log(3).unwrap();
  845. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  846. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  847. len += Ipv4Addr::new(10, 0, 0, 1)
  848. .write(&mut input[len..])
  849. .unwrap()
  850. .get();
  851. _ = len;
  852. let logger = logger();
  853. let () = log_buf(&input, logger).unwrap();
  854. testing_logger::validate(|captured_logs| {
  855. assert_eq!(captured_logs.len(), 1);
  856. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  857. assert_eq!(captured_logs[0].level, Level::Info);
  858. });
  859. }
  860. #[test]
  861. fn test_display_hint_ip_ipv4() {
  862. testing_logger::setup();
  863. let (mut len, mut input) = new_log(3).unwrap();
  864. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  865. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  866. len += IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))
  867. .write(&mut input[len..])
  868. .unwrap()
  869. .get();
  870. _ = len;
  871. let logger = logger();
  872. let () = log_buf(&input, logger).unwrap();
  873. testing_logger::validate(|captured_logs| {
  874. assert_eq!(captured_logs.len(), 1);
  875. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  876. assert_eq!(captured_logs[0].level, Level::Info);
  877. });
  878. }
  879. #[test]
  880. fn test_display_hint_ipv4_u32() {
  881. testing_logger::setup();
  882. let (mut len, mut input) = new_log(3).unwrap();
  883. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  884. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  885. // 10.0.0.1 as u32
  886. len += 167772161u32.write(&mut input[len..]).unwrap().get();
  887. _ = len;
  888. let logger = logger();
  889. let () = log_buf(&input, logger).unwrap();
  890. testing_logger::validate(|captured_logs| {
  891. assert_eq!(captured_logs.len(), 1);
  892. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  893. assert_eq!(captured_logs[0].level, Level::Info);
  894. });
  895. }
  896. #[test]
  897. fn test_display_hint_ipv6() {
  898. testing_logger::setup();
  899. let (mut len, mut input) = new_log(3).unwrap();
  900. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  901. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  902. len += Ipv6Addr::new(
  903. 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
  904. )
  905. .write(&mut input[len..])
  906. .unwrap()
  907. .get();
  908. _ = len;
  909. let logger = logger();
  910. let () = log_buf(&input, logger).unwrap();
  911. testing_logger::validate(|captured_logs| {
  912. assert_eq!(captured_logs.len(), 1);
  913. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  914. assert_eq!(captured_logs[0].level, Level::Info);
  915. });
  916. }
  917. #[test]
  918. fn test_display_hint_ip_ipv6() {
  919. testing_logger::setup();
  920. let (mut len, mut input) = new_log(3).unwrap();
  921. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  922. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  923. len += IpAddr::V6(Ipv6Addr::new(
  924. 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
  925. ))
  926. .write(&mut input[len..])
  927. .unwrap()
  928. .get();
  929. _ = len;
  930. let logger = logger();
  931. let () = log_buf(&input, logger).unwrap();
  932. testing_logger::validate(|captured_logs| {
  933. assert_eq!(captured_logs.len(), 1);
  934. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  935. assert_eq!(captured_logs[0].level, Level::Info);
  936. });
  937. }
  938. #[test]
  939. fn test_display_hint_ipv6_arr_u8_len_16() {
  940. testing_logger::setup();
  941. let (mut len, mut input) = new_log(3).unwrap();
  942. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  943. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  944. // 2001:db8::1:1 as byte array
  945. let ipv6_arr: [u8; 16] = [
  946. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  947. 0x00, 0x01,
  948. ];
  949. len += ipv6_arr.write(&mut input[len..]).unwrap().get();
  950. _ = len;
  951. let logger = logger();
  952. let () = log_buf(&input, logger).unwrap();
  953. testing_logger::validate(|captured_logs| {
  954. assert_eq!(captured_logs.len(), 1);
  955. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  956. assert_eq!(captured_logs[0].level, Level::Info);
  957. });
  958. }
  959. #[test]
  960. fn test_display_hint_ipv6_arr_u16_len_8() {
  961. testing_logger::setup();
  962. let (mut len, mut input) = new_log(3).unwrap();
  963. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  964. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  965. let ipv6 = std::net::Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0x1, 0x1);
  966. let ipv6_arr = ipv6.octets();
  967. len += ipv6_arr.write(&mut input[len..]).unwrap().get();
  968. _ = len;
  969. let logger = logger();
  970. let () = log_buf(&input, logger).unwrap();
  971. testing_logger::validate(|captured_logs| {
  972. assert_eq!(captured_logs.len(), 1);
  973. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  974. assert_eq!(captured_logs[0].level, Level::Info);
  975. });
  976. }
  977. #[test]
  978. fn test_display_hint_lower_mac() {
  979. testing_logger::setup();
  980. let (mut len, mut input) = new_log(3).unwrap();
  981. len += "mac: ".write(&mut input[len..]).unwrap().get();
  982. len += DisplayHint::LowerMac
  983. .write(&mut input[len..])
  984. .unwrap()
  985. .get();
  986. // 00:00:5e:00:53:af as byte array
  987. let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
  988. len += mac_arr.write(&mut input[len..]).unwrap().get();
  989. _ = len;
  990. let logger = logger();
  991. let () = log_buf(&input, logger).unwrap();
  992. testing_logger::validate(|captured_logs| {
  993. assert_eq!(captured_logs.len(), 1);
  994. assert_eq!(captured_logs[0].body, "mac: 00:00:5e:00:53:af");
  995. assert_eq!(captured_logs[0].level, Level::Info);
  996. });
  997. }
  998. #[test]
  999. fn test_display_hint_upper_mac() {
  1000. testing_logger::setup();
  1001. let (mut len, mut input) = new_log(3).unwrap();
  1002. len += "mac: ".write(&mut input[len..]).unwrap().get();
  1003. len += DisplayHint::UpperMac
  1004. .write(&mut input[len..])
  1005. .unwrap()
  1006. .get();
  1007. // 00:00:5E:00:53:AF as byte array
  1008. let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
  1009. len += mac_arr.write(&mut input[len..]).unwrap().get();
  1010. _ = len;
  1011. let logger = logger();
  1012. let () = log_buf(&input, logger).unwrap();
  1013. testing_logger::validate(|captured_logs| {
  1014. assert_eq!(captured_logs.len(), 1);
  1015. assert_eq!(captured_logs[0].body, "mac: 00:00:5E:00:53:AF");
  1016. assert_eq!(captured_logs[0].level, Level::Info);
  1017. });
  1018. }
  1019. }