lib.rs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  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. maps::{
  62. perf::{AsyncPerfEventArray, Events, PerfBufferError},
  63. Map, MapData, MapError, MapInfo,
  64. },
  65. programs::{loaded_programs, ProgramError},
  66. util::online_cpus,
  67. Ebpf, Pod,
  68. };
  69. use aya_log_common::{
  70. Argument, DisplayHint, Level, LogValueLength, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS,
  71. };
  72. use bytes::BytesMut;
  73. use log::{error, Log, Record};
  74. use thiserror::Error;
  75. #[allow(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. #[allow(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::InvalidOnlineCpu)? {
  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 LowerHexDebugFormatter;
  187. impl<T> Formatter<&[T]> for LowerHexDebugFormatter
  188. where
  189. T: LowerHex,
  190. {
  191. fn format(v: &[T]) -> String {
  192. let mut s = String::new();
  193. for v in v {
  194. let () = core::fmt::write(&mut s, format_args!("{v:x}")).unwrap();
  195. }
  196. s
  197. }
  198. }
  199. pub struct UpperHexFormatter;
  200. impl<T> Formatter<T> for UpperHexFormatter
  201. where
  202. T: UpperHex,
  203. {
  204. fn format(v: T) -> String {
  205. format!("{v:X}")
  206. }
  207. }
  208. pub struct UpperHexDebugFormatter;
  209. impl<T> Formatter<&[T]> for UpperHexDebugFormatter
  210. where
  211. T: UpperHex,
  212. {
  213. fn format(v: &[T]) -> String {
  214. let mut s = String::new();
  215. for v in v {
  216. let () = core::fmt::write(&mut s, format_args!("{v:X}")).unwrap();
  217. }
  218. s
  219. }
  220. }
  221. pub struct Ipv4Formatter;
  222. impl<T> Formatter<T> for Ipv4Formatter
  223. where
  224. T: Into<Ipv4Addr>,
  225. {
  226. fn format(v: T) -> String {
  227. v.into().to_string()
  228. }
  229. }
  230. pub struct Ipv6Formatter;
  231. impl<T> Formatter<T> for Ipv6Formatter
  232. where
  233. T: Into<Ipv6Addr>,
  234. {
  235. fn format(v: T) -> String {
  236. v.into().to_string()
  237. }
  238. }
  239. pub struct LowerMacFormatter;
  240. impl Formatter<[u8; 6]> for LowerMacFormatter {
  241. fn format(v: [u8; 6]) -> String {
  242. format!(
  243. "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
  244. v[0], v[1], v[2], v[3], v[4], v[5]
  245. )
  246. }
  247. }
  248. pub struct UpperMacFormatter;
  249. impl Formatter<[u8; 6]> for UpperMacFormatter {
  250. fn format(v: [u8; 6]) -> String {
  251. format!(
  252. "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
  253. v[0], v[1], v[2], v[3], v[4], v[5]
  254. )
  255. }
  256. }
  257. trait Format {
  258. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()>;
  259. }
  260. impl Format for &[u8] {
  261. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  262. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  263. Some(DisplayHint::LowerHex) => Ok(LowerHexDebugFormatter::format(self)),
  264. Some(DisplayHint::UpperHex) => Ok(UpperHexDebugFormatter::format(self)),
  265. _ => Err(()),
  266. }
  267. }
  268. }
  269. impl Format for u32 {
  270. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  271. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  272. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  273. Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
  274. Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
  275. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  276. Some(DisplayHint::LowerMac) => Err(()),
  277. Some(DisplayHint::UpperMac) => Err(()),
  278. _ => Ok(DefaultFormatter::format(self)),
  279. }
  280. }
  281. }
  282. impl Format for Ipv4Addr {
  283. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  284. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  285. Some(DisplayHint::Default) => Ok(Ipv4Formatter::format(*self)),
  286. Some(DisplayHint::LowerHex) => Err(()),
  287. Some(DisplayHint::UpperHex) => Err(()),
  288. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  289. Some(DisplayHint::LowerMac) => Err(()),
  290. Some(DisplayHint::UpperMac) => Err(()),
  291. None => Ok(Ipv4Formatter::format(*self)),
  292. }
  293. }
  294. }
  295. impl Format for Ipv6Addr {
  296. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  297. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  298. Some(DisplayHint::Default) => Ok(Ipv6Formatter::format(*self)),
  299. Some(DisplayHint::LowerHex) => Err(()),
  300. Some(DisplayHint::UpperHex) => Err(()),
  301. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  302. Some(DisplayHint::LowerMac) => Err(()),
  303. Some(DisplayHint::UpperMac) => Err(()),
  304. None => Ok(Ipv6Formatter::format(*self)),
  305. }
  306. }
  307. }
  308. impl Format for [u8; 4] {
  309. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  310. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  311. Some(DisplayHint::Default) => Ok(Ipv4Formatter::format(*self)),
  312. Some(DisplayHint::LowerHex) => Err(()),
  313. Some(DisplayHint::UpperHex) => Err(()),
  314. Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
  315. Some(DisplayHint::LowerMac) => Err(()),
  316. Some(DisplayHint::UpperMac) => Err(()),
  317. None => Ok(Ipv4Formatter::format(*self)),
  318. }
  319. }
  320. }
  321. impl Format for [u8; 6] {
  322. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  323. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  324. Some(DisplayHint::Default) => Err(()),
  325. Some(DisplayHint::LowerHex) => Err(()),
  326. Some(DisplayHint::UpperHex) => Err(()),
  327. Some(DisplayHint::Ip) => Err(()),
  328. Some(DisplayHint::LowerMac) => Ok(LowerMacFormatter::format(*self)),
  329. Some(DisplayHint::UpperMac) => Ok(UpperMacFormatter::format(*self)),
  330. _ => Err(()),
  331. }
  332. }
  333. }
  334. impl Format for [u8; 16] {
  335. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  336. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  337. Some(DisplayHint::Default) => Err(()),
  338. Some(DisplayHint::LowerHex) => Err(()),
  339. Some(DisplayHint::UpperHex) => Err(()),
  340. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  341. Some(DisplayHint::LowerMac) => Err(()),
  342. Some(DisplayHint::UpperMac) => Err(()),
  343. _ => Err(()),
  344. }
  345. }
  346. }
  347. impl Format for [u16; 8] {
  348. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  349. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  350. Some(DisplayHint::Default) => Err(()),
  351. Some(DisplayHint::LowerHex) => Err(()),
  352. Some(DisplayHint::UpperHex) => Err(()),
  353. Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
  354. Some(DisplayHint::LowerMac) => Err(()),
  355. Some(DisplayHint::UpperMac) => Err(()),
  356. _ => Err(()),
  357. }
  358. }
  359. }
  360. macro_rules! impl_format {
  361. ($type:ident) => {
  362. impl Format for $type {
  363. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  364. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  365. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  366. Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
  367. Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
  368. Some(DisplayHint::Ip) => Err(()),
  369. Some(DisplayHint::LowerMac) => Err(()),
  370. Some(DisplayHint::UpperMac) => Err(()),
  371. _ => Ok(DefaultFormatter::format(self)),
  372. }
  373. }
  374. }
  375. };
  376. }
  377. impl_format!(i8);
  378. impl_format!(i16);
  379. impl_format!(i32);
  380. impl_format!(i64);
  381. impl_format!(isize);
  382. impl_format!(u8);
  383. impl_format!(u16);
  384. impl_format!(u64);
  385. impl_format!(usize);
  386. macro_rules! impl_format_float {
  387. ($type:ident) => {
  388. impl Format for $type {
  389. fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
  390. match last_hint.map(|DisplayHintWrapper(dh)| dh) {
  391. Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
  392. Some(DisplayHint::LowerHex) => Err(()),
  393. Some(DisplayHint::UpperHex) => Err(()),
  394. Some(DisplayHint::Ip) => Err(()),
  395. Some(DisplayHint::LowerMac) => Err(()),
  396. Some(DisplayHint::UpperMac) => Err(()),
  397. _ => Ok(DefaultFormatter::format(self)),
  398. }
  399. }
  400. }
  401. };
  402. }
  403. impl_format_float!(f32);
  404. impl_format_float!(f64);
  405. #[derive(Error, Debug)]
  406. pub enum Error {
  407. #[error("log event array {} doesn't exist", MAP_NAME)]
  408. MapNotFound,
  409. #[error("error opening log event array")]
  410. MapError(#[from] MapError),
  411. #[error("error opening log buffer")]
  412. PerfBufferError(#[from] PerfBufferError),
  413. #[error("invalid /sys/devices/system/cpu/online format")]
  414. InvalidOnlineCpu(#[source] io::Error),
  415. #[error("program not found")]
  416. ProgramNotFound,
  417. #[error(transparent)]
  418. ProgramError(#[from] ProgramError),
  419. }
  420. fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
  421. let mut target = None;
  422. let mut level = None;
  423. let mut module = None;
  424. let mut file = None;
  425. let mut line = None;
  426. let mut num_args = None;
  427. for _ in 0..LOG_FIELDS {
  428. let (RecordFieldWrapper(tag), value, rest) = try_read(buf)?;
  429. match tag {
  430. RecordField::Target => {
  431. target = Some(str::from_utf8(value).map_err(|_| ())?);
  432. }
  433. RecordField::Level => {
  434. level = Some({
  435. let level = unsafe { ptr::read_unaligned(value.as_ptr() as *const _) };
  436. match level {
  437. Level::Error => log::Level::Error,
  438. Level::Warn => log::Level::Warn,
  439. Level::Info => log::Level::Info,
  440. Level::Debug => log::Level::Debug,
  441. Level::Trace => log::Level::Trace,
  442. }
  443. })
  444. }
  445. RecordField::Module => {
  446. module = Some(str::from_utf8(value).map_err(|_| ())?);
  447. }
  448. RecordField::File => {
  449. file = Some(str::from_utf8(value).map_err(|_| ())?);
  450. }
  451. RecordField::Line => {
  452. line = Some(u32::from_ne_bytes(value.try_into().map_err(|_| ())?));
  453. }
  454. RecordField::NumArgs => {
  455. num_args = Some(usize::from_ne_bytes(value.try_into().map_err(|_| ())?));
  456. }
  457. }
  458. buf = rest;
  459. }
  460. let mut full_log_msg = String::new();
  461. let mut last_hint: Option<DisplayHintWrapper> = None;
  462. for _ in 0..num_args.ok_or(())? {
  463. let (ArgumentWrapper(tag), value, rest) = try_read(buf)?;
  464. match tag {
  465. Argument::DisplayHint => {
  466. last_hint = Some(unsafe { ptr::read_unaligned(value.as_ptr() as *const _) });
  467. }
  468. Argument::I8 => {
  469. full_log_msg.push_str(
  470. &i8::from_ne_bytes(value.try_into().map_err(|_| ())?)
  471. .format(last_hint.take())?,
  472. );
  473. }
  474. Argument::I16 => {
  475. full_log_msg.push_str(
  476. &i16::from_ne_bytes(value.try_into().map_err(|_| ())?)
  477. .format(last_hint.take())?,
  478. );
  479. }
  480. Argument::I32 => {
  481. full_log_msg.push_str(
  482. &i32::from_ne_bytes(value.try_into().map_err(|_| ())?)
  483. .format(last_hint.take())?,
  484. );
  485. }
  486. Argument::I64 => {
  487. full_log_msg.push_str(
  488. &i64::from_ne_bytes(value.try_into().map_err(|_| ())?)
  489. .format(last_hint.take())?,
  490. );
  491. }
  492. Argument::Isize => {
  493. full_log_msg.push_str(
  494. &isize::from_ne_bytes(value.try_into().map_err(|_| ())?)
  495. .format(last_hint.take())?,
  496. );
  497. }
  498. Argument::U8 => {
  499. full_log_msg.push_str(
  500. &u8::from_ne_bytes(value.try_into().map_err(|_| ())?)
  501. .format(last_hint.take())?,
  502. );
  503. }
  504. Argument::U16 => {
  505. full_log_msg.push_str(
  506. &u16::from_ne_bytes(value.try_into().map_err(|_| ())?)
  507. .format(last_hint.take())?,
  508. );
  509. }
  510. Argument::U32 => {
  511. full_log_msg.push_str(
  512. &u32::from_ne_bytes(value.try_into().map_err(|_| ())?)
  513. .format(last_hint.take())?,
  514. );
  515. }
  516. Argument::U64 => {
  517. full_log_msg.push_str(
  518. &u64::from_ne_bytes(value.try_into().map_err(|_| ())?)
  519. .format(last_hint.take())?,
  520. );
  521. }
  522. Argument::Usize => {
  523. full_log_msg.push_str(
  524. &usize::from_ne_bytes(value.try_into().map_err(|_| ())?)
  525. .format(last_hint.take())?,
  526. );
  527. }
  528. Argument::F32 => {
  529. full_log_msg.push_str(
  530. &f32::from_ne_bytes(value.try_into().map_err(|_| ())?)
  531. .format(last_hint.take())?,
  532. );
  533. }
  534. Argument::F64 => {
  535. full_log_msg.push_str(
  536. &f64::from_ne_bytes(value.try_into().map_err(|_| ())?)
  537. .format(last_hint.take())?,
  538. );
  539. }
  540. Argument::Ipv4Addr => {
  541. let value: [u8; 4] = value.try_into().map_err(|_| ())?;
  542. let value = Ipv4Addr::from(value);
  543. full_log_msg.push_str(&value.format(last_hint.take())?)
  544. }
  545. Argument::Ipv6Addr => {
  546. let value: [u8; 16] = value.try_into().map_err(|_| ())?;
  547. let value = Ipv6Addr::from(value);
  548. full_log_msg.push_str(&value.format(last_hint.take())?)
  549. }
  550. Argument::ArrU8Len4 => {
  551. let value: [u8; 4] = value.try_into().map_err(|_| ())?;
  552. full_log_msg.push_str(&value.format(last_hint.take())?);
  553. }
  554. Argument::ArrU8Len6 => {
  555. let value: [u8; 6] = value.try_into().map_err(|_| ())?;
  556. full_log_msg.push_str(&value.format(last_hint.take())?);
  557. }
  558. Argument::ArrU8Len16 => {
  559. let value: [u8; 16] = value.try_into().map_err(|_| ())?;
  560. full_log_msg.push_str(&value.format(last_hint.take())?);
  561. }
  562. Argument::ArrU16Len8 => {
  563. let data: [u8; 16] = value.try_into().map_err(|_| ())?;
  564. let mut value: [u16; 8] = Default::default();
  565. for (i, s) in data.chunks_exact(2).enumerate() {
  566. value[i] = ((s[1] as u16) << 8) | s[0] as u16;
  567. }
  568. full_log_msg.push_str(&value.format(last_hint.take())?);
  569. }
  570. Argument::Bytes => {
  571. full_log_msg.push_str(&value.format(last_hint.take())?);
  572. }
  573. Argument::Str => match str::from_utf8(value) {
  574. Ok(v) => {
  575. full_log_msg.push_str(v);
  576. }
  577. Err(e) => error!("received invalid utf8 string: {}", e),
  578. },
  579. }
  580. buf = rest;
  581. }
  582. logger.log(
  583. &Record::builder()
  584. .args(format_args!("{full_log_msg}"))
  585. .target(target.ok_or(())?)
  586. .level(level.ok_or(())?)
  587. .module_path(module)
  588. .file(file)
  589. .line(line)
  590. .build(),
  591. );
  592. logger.flush();
  593. Ok(())
  594. }
  595. fn try_read<T: Pod>(mut buf: &[u8]) -> Result<(T, &[u8], &[u8]), ()> {
  596. if buf.len() < mem::size_of::<T>() + mem::size_of::<LogValueLength>() {
  597. return Err(());
  598. }
  599. let tag = unsafe { ptr::read_unaligned(buf.as_ptr() as *const T) };
  600. buf = &buf[mem::size_of::<T>()..];
  601. let len =
  602. LogValueLength::from_ne_bytes(buf[..mem::size_of::<LogValueLength>()].try_into().unwrap());
  603. buf = &buf[mem::size_of::<LogValueLength>()..];
  604. let len: usize = len.into();
  605. if buf.len() < len {
  606. return Err(());
  607. }
  608. let (value, rest) = buf.split_at(len);
  609. Ok((tag, value, rest))
  610. }
  611. #[cfg(test)]
  612. mod test {
  613. use std::net::IpAddr;
  614. use aya_log_common::{write_record_header, WriteToBuf};
  615. use log::{logger, Level};
  616. use super::*;
  617. fn new_log(args: usize) -> Option<(usize, Vec<u8>)> {
  618. let mut buf = vec![0; 8192];
  619. let len = write_record_header(
  620. &mut buf,
  621. "test",
  622. aya_log_common::Level::Info,
  623. "test",
  624. "test.rs",
  625. 123,
  626. args,
  627. )?;
  628. Some((len.get(), buf))
  629. }
  630. #[test]
  631. fn test_str() {
  632. testing_logger::setup();
  633. let (mut len, mut input) = new_log(1).unwrap();
  634. len += "test".write(&mut input[len..]).unwrap().get();
  635. _ = len;
  636. let logger = logger();
  637. let () = log_buf(&input, logger).unwrap();
  638. testing_logger::validate(|captured_logs| {
  639. assert_eq!(captured_logs.len(), 1);
  640. assert_eq!(captured_logs[0].body, "test");
  641. assert_eq!(captured_logs[0].level, Level::Info);
  642. });
  643. }
  644. #[test]
  645. fn test_str_with_args() {
  646. testing_logger::setup();
  647. let (mut len, mut input) = new_log(2).unwrap();
  648. len += "hello ".write(&mut input[len..]).unwrap().get();
  649. len += "test".write(&mut input[len..]).unwrap().get();
  650. _ = len;
  651. let logger = logger();
  652. let () = log_buf(&input, logger).unwrap();
  653. testing_logger::validate(|captured_logs| {
  654. assert_eq!(captured_logs.len(), 1);
  655. assert_eq!(captured_logs[0].body, "hello test");
  656. assert_eq!(captured_logs[0].level, Level::Info);
  657. });
  658. }
  659. #[test]
  660. fn test_bytes() {
  661. testing_logger::setup();
  662. let (mut len, mut input) = new_log(2).unwrap();
  663. len += DisplayHint::LowerHex
  664. .write(&mut input[len..])
  665. .unwrap()
  666. .get();
  667. len += [0xde, 0xad].write(&mut input[len..]).unwrap().get();
  668. _ = len;
  669. let logger = logger();
  670. let () = log_buf(&input, logger).unwrap();
  671. testing_logger::validate(|captured_logs| {
  672. assert_eq!(captured_logs.len(), 1);
  673. assert_eq!(captured_logs[0].body, "dead");
  674. assert_eq!(captured_logs[0].level, Level::Info);
  675. });
  676. }
  677. #[test]
  678. fn test_bytes_with_args() {
  679. testing_logger::setup();
  680. let (mut len, mut input) = new_log(5).unwrap();
  681. len += DisplayHint::LowerHex
  682. .write(&mut input[len..])
  683. .unwrap()
  684. .get();
  685. len += [0xde, 0xad].write(&mut input[len..]).unwrap().get();
  686. len += " ".write(&mut input[len..]).unwrap().get();
  687. len += DisplayHint::UpperHex
  688. .write(&mut input[len..])
  689. .unwrap()
  690. .get();
  691. len += [0xbe, 0xef].write(&mut input[len..]).unwrap().get();
  692. _ = len;
  693. let logger = logger();
  694. let () = log_buf(&input, logger).unwrap();
  695. testing_logger::validate(|captured_logs| {
  696. assert_eq!(captured_logs.len(), 1);
  697. assert_eq!(captured_logs[0].body, "dead BEEF");
  698. assert_eq!(captured_logs[0].level, Level::Info);
  699. });
  700. }
  701. #[test]
  702. fn test_display_hint_default() {
  703. testing_logger::setup();
  704. let (mut len, mut input) = new_log(3).unwrap();
  705. len += "default hint: ".write(&mut input[len..]).unwrap().get();
  706. len += DisplayHint::Default.write(&mut input[len..]).unwrap().get();
  707. len += 14.write(&mut input[len..]).unwrap().get();
  708. _ = len;
  709. let logger = logger();
  710. let () = log_buf(&input, logger).unwrap();
  711. testing_logger::validate(|captured_logs| {
  712. assert_eq!(captured_logs.len(), 1);
  713. assert_eq!(captured_logs[0].body, "default hint: 14");
  714. assert_eq!(captured_logs[0].level, Level::Info);
  715. });
  716. }
  717. #[test]
  718. fn test_display_hint_lower_hex() {
  719. testing_logger::setup();
  720. let (mut len, mut input) = new_log(3).unwrap();
  721. len += "lower hex: ".write(&mut input[len..]).unwrap().get();
  722. len += DisplayHint::LowerHex
  723. .write(&mut input[len..])
  724. .unwrap()
  725. .get();
  726. len += 200.write(&mut input[len..]).unwrap().get();
  727. _ = len;
  728. let logger = logger();
  729. let () = log_buf(&input, logger).unwrap();
  730. testing_logger::validate(|captured_logs| {
  731. assert_eq!(captured_logs.len(), 1);
  732. assert_eq!(captured_logs[0].body, "lower hex: c8");
  733. assert_eq!(captured_logs[0].level, Level::Info);
  734. });
  735. }
  736. #[test]
  737. fn test_display_hint_upper_hex() {
  738. testing_logger::setup();
  739. let (mut len, mut input) = new_log(3).unwrap();
  740. len += "upper hex: ".write(&mut input[len..]).unwrap().get();
  741. len += DisplayHint::UpperHex
  742. .write(&mut input[len..])
  743. .unwrap()
  744. .get();
  745. len += 200.write(&mut input[len..]).unwrap().get();
  746. _ = len;
  747. let logger = logger();
  748. let () = log_buf(&input, logger).unwrap();
  749. testing_logger::validate(|captured_logs| {
  750. assert_eq!(captured_logs.len(), 1);
  751. assert_eq!(captured_logs[0].body, "upper hex: C8");
  752. assert_eq!(captured_logs[0].level, Level::Info);
  753. });
  754. }
  755. #[test]
  756. fn test_display_hint_ipv4() {
  757. testing_logger::setup();
  758. let (mut len, mut input) = new_log(3).unwrap();
  759. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  760. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  761. len += Ipv4Addr::new(10, 0, 0, 1)
  762. .write(&mut input[len..])
  763. .unwrap()
  764. .get();
  765. _ = len;
  766. let logger = logger();
  767. let () = log_buf(&input, logger).unwrap();
  768. testing_logger::validate(|captured_logs| {
  769. assert_eq!(captured_logs.len(), 1);
  770. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  771. assert_eq!(captured_logs[0].level, Level::Info);
  772. });
  773. }
  774. #[test]
  775. fn test_display_hint_ip_ipv4() {
  776. testing_logger::setup();
  777. let (mut len, mut input) = new_log(3).unwrap();
  778. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  779. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  780. len += IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))
  781. .write(&mut input[len..])
  782. .unwrap()
  783. .get();
  784. _ = len;
  785. let logger = logger();
  786. let () = log_buf(&input, logger).unwrap();
  787. testing_logger::validate(|captured_logs| {
  788. assert_eq!(captured_logs.len(), 1);
  789. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  790. assert_eq!(captured_logs[0].level, Level::Info);
  791. });
  792. }
  793. #[test]
  794. fn test_display_hint_ipv4_u32() {
  795. testing_logger::setup();
  796. let (mut len, mut input) = new_log(3).unwrap();
  797. len += "ipv4: ".write(&mut input[len..]).unwrap().get();
  798. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  799. // 10.0.0.1 as u32
  800. len += 167772161u32.write(&mut input[len..]).unwrap().get();
  801. _ = len;
  802. let logger = logger();
  803. let () = log_buf(&input, logger).unwrap();
  804. testing_logger::validate(|captured_logs| {
  805. assert_eq!(captured_logs.len(), 1);
  806. assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
  807. assert_eq!(captured_logs[0].level, Level::Info);
  808. });
  809. }
  810. #[test]
  811. fn test_display_hint_ipv6() {
  812. testing_logger::setup();
  813. let (mut len, mut input) = new_log(3).unwrap();
  814. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  815. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  816. len += Ipv6Addr::new(
  817. 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
  818. )
  819. .write(&mut input[len..])
  820. .unwrap()
  821. .get();
  822. _ = len;
  823. let logger = logger();
  824. let () = log_buf(&input, logger).unwrap();
  825. testing_logger::validate(|captured_logs| {
  826. assert_eq!(captured_logs.len(), 1);
  827. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  828. assert_eq!(captured_logs[0].level, Level::Info);
  829. });
  830. }
  831. #[test]
  832. fn test_display_hint_ip_ipv6() {
  833. testing_logger::setup();
  834. let (mut len, mut input) = new_log(3).unwrap();
  835. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  836. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  837. len += IpAddr::V6(Ipv6Addr::new(
  838. 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
  839. ))
  840. .write(&mut input[len..])
  841. .unwrap()
  842. .get();
  843. _ = len;
  844. let logger = logger();
  845. let () = log_buf(&input, logger).unwrap();
  846. testing_logger::validate(|captured_logs| {
  847. assert_eq!(captured_logs.len(), 1);
  848. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  849. assert_eq!(captured_logs[0].level, Level::Info);
  850. });
  851. }
  852. #[test]
  853. fn test_display_hint_ipv6_arr_u8_len_16() {
  854. testing_logger::setup();
  855. let (mut len, mut input) = new_log(3).unwrap();
  856. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  857. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  858. // 2001:db8::1:1 as byte array
  859. let ipv6_arr: [u8; 16] = [
  860. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  861. 0x00, 0x01,
  862. ];
  863. len += ipv6_arr.write(&mut input[len..]).unwrap().get();
  864. _ = len;
  865. let logger = logger();
  866. let () = log_buf(&input, logger).unwrap();
  867. testing_logger::validate(|captured_logs| {
  868. assert_eq!(captured_logs.len(), 1);
  869. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  870. assert_eq!(captured_logs[0].level, Level::Info);
  871. });
  872. }
  873. #[test]
  874. fn test_display_hint_ipv6_arr_u16_len_8() {
  875. testing_logger::setup();
  876. let (mut len, mut input) = new_log(3).unwrap();
  877. len += "ipv6: ".write(&mut input[len..]).unwrap().get();
  878. len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get();
  879. // 2001:db8::1:1 as u16 array
  880. #[cfg(target_endian = "little")]
  881. let ipv6_arr: [u16; 8] = [
  882. 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
  883. ];
  884. #[cfg(target_endian = "big")]
  885. let ipv6_arr: [u16; 8] = [
  886. 0x0120, 0xb80d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100,
  887. ];
  888. len += ipv6_arr.write(&mut input[len..]).unwrap().get();
  889. _ = len;
  890. let logger = logger();
  891. let () = log_buf(&input, logger).unwrap();
  892. testing_logger::validate(|captured_logs| {
  893. assert_eq!(captured_logs.len(), 1);
  894. assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
  895. assert_eq!(captured_logs[0].level, Level::Info);
  896. });
  897. }
  898. #[test]
  899. fn test_display_hint_lower_mac() {
  900. testing_logger::setup();
  901. let (mut len, mut input) = new_log(3).unwrap();
  902. len += "mac: ".write(&mut input[len..]).unwrap().get();
  903. len += DisplayHint::LowerMac
  904. .write(&mut input[len..])
  905. .unwrap()
  906. .get();
  907. // 00:00:5e:00:53:af as byte array
  908. let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
  909. len += mac_arr.write(&mut input[len..]).unwrap().get();
  910. _ = len;
  911. let logger = logger();
  912. let () = log_buf(&input, logger).unwrap();
  913. testing_logger::validate(|captured_logs| {
  914. assert_eq!(captured_logs.len(), 1);
  915. assert_eq!(captured_logs[0].body, "mac: 00:00:5e:00:53:af");
  916. assert_eq!(captured_logs[0].level, Level::Info);
  917. });
  918. }
  919. #[test]
  920. fn test_display_hint_upper_mac() {
  921. testing_logger::setup();
  922. let (mut len, mut input) = new_log(3).unwrap();
  923. len += "mac: ".write(&mut input[len..]).unwrap().get();
  924. len += DisplayHint::UpperMac
  925. .write(&mut input[len..])
  926. .unwrap()
  927. .get();
  928. // 00:00:5E:00:53:AF as byte array
  929. let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
  930. len += mac_arr.write(&mut input[len..]).unwrap().get();
  931. _ = len;
  932. let logger = logger();
  933. let () = log_buf(&input, logger).unwrap();
  934. testing_logger::validate(|captured_logs| {
  935. assert_eq!(captured_logs.len(), 1);
  936. assert_eq!(captured_logs[0].body, "mac: 00:00:5E:00:53:AF");
  937. assert_eq!(captured_logs[0].level, Level::Info);
  938. });
  939. }
  940. }