|  | @@ -49,11 +49,16 @@
 | 
	
		
			
				|  |  |  //! [Log]: https://docs.rs/log/0.4.14/log/trait.Log.html
 | 
	
		
			
				|  |  |  //! [log]: https://docs.rs/log
 | 
	
		
			
				|  |  |  //!
 | 
	
		
			
				|  |  | -use std::{io, mem, ptr, str, sync::Arc};
 | 
	
		
			
				|  |  | +use std::{
 | 
	
		
			
				|  |  | +    fmt::{LowerHex, UpperHex},
 | 
	
		
			
				|  |  | +    io, mem,
 | 
	
		
			
				|  |  | +    net::{Ipv4Addr, Ipv6Addr},
 | 
	
		
			
				|  |  | +    ptr, slice, str,
 | 
	
		
			
				|  |  | +    sync::Arc,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use aya_log_common::{ArgType, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS};
 | 
	
		
			
				|  |  | +use aya_log_common::{Argument, DisplayHint, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS};
 | 
	
		
			
				|  |  |  use bytes::BytesMut;
 | 
	
		
			
				|  |  | -use dyn_fmt::AsStrFormatExt;
 | 
	
		
			
				|  |  |  use log::{error, Level, Log, Record};
 | 
	
		
			
				|  |  |  use thiserror::Error;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -112,6 +117,151 @@ impl BpfLogger {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +pub trait Formatter<T> {
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub struct DefaultFormatter;
 | 
	
		
			
				|  |  | +impl<T> Formatter<T> for DefaultFormatter
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    T: ToString,
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String {
 | 
	
		
			
				|  |  | +        v.to_string()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub struct LowerHexFormatter;
 | 
	
		
			
				|  |  | +impl<T> Formatter<T> for LowerHexFormatter
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    T: LowerHex,
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String {
 | 
	
		
			
				|  |  | +        format!("{:x}", v)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub struct UpperHexFormatter;
 | 
	
		
			
				|  |  | +impl<T> Formatter<T> for UpperHexFormatter
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    T: UpperHex,
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String {
 | 
	
		
			
				|  |  | +        format!("{:X}", v)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub struct Ipv4Formatter;
 | 
	
		
			
				|  |  | +impl<T> Formatter<T> for Ipv4Formatter
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    T: Into<Ipv4Addr>,
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String {
 | 
	
		
			
				|  |  | +        v.into().to_string()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub struct Ipv6Formatter;
 | 
	
		
			
				|  |  | +impl<T> Formatter<T> for Ipv6Formatter
 | 
	
		
			
				|  |  | +where
 | 
	
		
			
				|  |  | +    T: Into<Ipv6Addr>,
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    fn format(v: T) -> String {
 | 
	
		
			
				|  |  | +        v.into().to_string()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +trait Format {
 | 
	
		
			
				|  |  | +    fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()>;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl Format for u32 {
 | 
	
		
			
				|  |  | +    fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
 | 
	
		
			
				|  |  | +        match last_hint {
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv4) => Ok(Ipv4Formatter::format(*self)),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv6) => Err(()),
 | 
	
		
			
				|  |  | +            _ => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl Format for [u8; 16] {
 | 
	
		
			
				|  |  | +    fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
 | 
	
		
			
				|  |  | +        match last_hint {
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Default) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::LowerHex) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::UpperHex) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv4) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
 | 
	
		
			
				|  |  | +            _ => Err(()),
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl Format for [u16; 8] {
 | 
	
		
			
				|  |  | +    fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
 | 
	
		
			
				|  |  | +        match last_hint {
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Default) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::LowerHex) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::UpperHex) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv4) => Err(()),
 | 
	
		
			
				|  |  | +            Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
 | 
	
		
			
				|  |  | +            _ => Err(()),
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +macro_rules! impl_format {
 | 
	
		
			
				|  |  | +    ($type:ident) => {
 | 
	
		
			
				|  |  | +        impl Format for $type {
 | 
	
		
			
				|  |  | +            fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
 | 
	
		
			
				|  |  | +                match last_hint {
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::LowerHex) => Ok(LowerHexFormatter::format(self)),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Ipv4) => Err(()),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Ipv6) => Err(()),
 | 
	
		
			
				|  |  | +                    _ => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl_format!(i8);
 | 
	
		
			
				|  |  | +impl_format!(i16);
 | 
	
		
			
				|  |  | +impl_format!(i32);
 | 
	
		
			
				|  |  | +impl_format!(i64);
 | 
	
		
			
				|  |  | +impl_format!(isize);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl_format!(u8);
 | 
	
		
			
				|  |  | +impl_format!(u16);
 | 
	
		
			
				|  |  | +impl_format!(u64);
 | 
	
		
			
				|  |  | +impl_format!(usize);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +macro_rules! impl_format_float {
 | 
	
		
			
				|  |  | +    ($type:ident) => {
 | 
	
		
			
				|  |  | +        impl Format for $type {
 | 
	
		
			
				|  |  | +            fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
 | 
	
		
			
				|  |  | +                match last_hint {
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Default) => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::LowerHex) => Err(()),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::UpperHex) => Err(()),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Ipv4) => Err(()),
 | 
	
		
			
				|  |  | +                    Some(DisplayHint::Ipv6) => Err(()),
 | 
	
		
			
				|  |  | +                    _ => Ok(DefaultFormatter::format(self)),
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl_format_float!(f32);
 | 
	
		
			
				|  |  | +impl_format_float!(f64);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #[derive(Copy, Clone, Debug)]
 | 
	
		
			
				|  |  |  struct DefaultLogger;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -147,7 +297,6 @@ fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
 | 
	
		
			
				|  |  |      let mut module = None;
 | 
	
		
			
				|  |  |      let mut file = None;
 | 
	
		
			
				|  |  |      let mut line = None;
 | 
	
		
			
				|  |  | -    let mut log = None;
 | 
	
		
			
				|  |  |      let mut num_args = None;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for _ in 0..LOG_FIELDS {
 | 
	
	
		
			
				|  | @@ -172,97 +321,113 @@ fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
 | 
	
		
			
				|  |  |              RecordField::NumArgs => {
 | 
	
		
			
				|  |  |                  num_args = Some(usize::from_ne_bytes(attr.value.try_into().map_err(|_| ())?));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            RecordField::Log => {
 | 
	
		
			
				|  |  | -                log = Some(std::str::from_utf8(attr.value).map_err(|_| ())?);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          buf = rest;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let log_msg = log.ok_or(())?;
 | 
	
		
			
				|  |  | -    let full_log_msg = match num_args {
 | 
	
		
			
				|  |  | -        Some(n) => {
 | 
	
		
			
				|  |  | -            let mut args: Vec<String> = Vec::new();
 | 
	
		
			
				|  |  | -            for _ in 0..n {
 | 
	
		
			
				|  |  | -                let (attr, rest) = unsafe { TagLenValue::<'_, ArgType>::try_read(buf)? };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                match attr.tag {
 | 
	
		
			
				|  |  | -                    ArgType::I8 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            i8::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::I16 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            i16::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::I32 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            i32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::I64 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            i64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::Isize => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            isize::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | -                                .to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::U8 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            u8::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::U16 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            u16::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::U32 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            u32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::U64 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            u64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::Usize => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            usize::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | -                                .to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::F32 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            f32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::F64 => {
 | 
	
		
			
				|  |  | -                        args.push(
 | 
	
		
			
				|  |  | -                            f64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?).to_string(),
 | 
	
		
			
				|  |  | -                        );
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    ArgType::Str => match str::from_utf8(attr.value) {
 | 
	
		
			
				|  |  | -                        Ok(v) => args.push(v.to_string()),
 | 
	
		
			
				|  |  | -                        Err(e) => error!("received invalid utf8 string: {}", e),
 | 
	
		
			
				|  |  | -                    },
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +    let mut full_log_msg = String::new();
 | 
	
		
			
				|  |  | +    let mut last_hint: Option<DisplayHint> = None;
 | 
	
		
			
				|  |  | +    for _ in 0..num_args.ok_or(())? {
 | 
	
		
			
				|  |  | +        let (attr, rest) = unsafe { TagLenValue::<'_, Argument>::try_read(buf)? };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                buf = rest;
 | 
	
		
			
				|  |  | +        match attr.tag {
 | 
	
		
			
				|  |  | +            Argument::DisplayHint => {
 | 
	
		
			
				|  |  | +                last_hint = Some(unsafe { ptr::read_unaligned(attr.value.as_ptr() as *const _) });
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            log_msg.format(&args)
 | 
	
		
			
				|  |  | +            Argument::I8 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &i8::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::I16 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &i16::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::I32 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &i32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::I64 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &i64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::Isize => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &isize::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::U8 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &u8::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::U16 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &u16::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::U32 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &u32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::U64 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &u64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::Usize => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &usize::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::F32 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &f32::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::F64 => {
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(
 | 
	
		
			
				|  |  | +                    &f64::from_ne_bytes(attr.value.try_into().map_err(|_| ())?)
 | 
	
		
			
				|  |  | +                        .format(last_hint.take())?,
 | 
	
		
			
				|  |  | +                );
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::ArrU8Len16 => {
 | 
	
		
			
				|  |  | +                let value: [u8; 16] = attr.value.try_into().map_err(|_| ())?;
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(&value.format(last_hint.take())?);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::ArrU16Len8 => {
 | 
	
		
			
				|  |  | +                let ptr = attr.value.as_ptr().cast::<u16>();
 | 
	
		
			
				|  |  | +                let slice = unsafe { slice::from_raw_parts(ptr, 8) };
 | 
	
		
			
				|  |  | +                let mut value: [u16; 8] = Default::default();
 | 
	
		
			
				|  |  | +                value.copy_from_slice(slice);
 | 
	
		
			
				|  |  | +                full_log_msg.push_str(&value.format(last_hint.take())?);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Argument::Str => match str::from_utf8(attr.value) {
 | 
	
		
			
				|  |  | +                Ok(v) => {
 | 
	
		
			
				|  |  | +                    full_log_msg.push_str(v);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                Err(e) => error!("received invalid utf8 string: {}", e),
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        None => log_msg.to_string(),
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        buf = rest;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      logger.log(
 | 
	
		
			
				|  |  |          &Record::builder()
 | 
	
	
		
			
				|  | @@ -312,13 +477,13 @@ impl<'a, T: Pod> TagLenValue<'a, T> {
 | 
	
		
			
				|  |  |  #[cfg(test)]
 | 
	
		
			
				|  |  |  mod test {
 | 
	
		
			
				|  |  |      use super::*;
 | 
	
		
			
				|  |  | -    use aya_log_common::{write_record_header, write_record_message, WriteToBuf};
 | 
	
		
			
				|  |  | +    use aya_log_common::{write_record_header, WriteToBuf};
 | 
	
		
			
				|  |  |      use log::logger;
 | 
	
		
			
				|  |  |      use testing_logger;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn new_log(msg: &str, args: usize) -> Result<(usize, Vec<u8>), ()> {
 | 
	
		
			
				|  |  | +    fn new_log(args: usize) -> Result<(usize, Vec<u8>), ()> {
 | 
	
		
			
				|  |  |          let mut buf = vec![0; 8192];
 | 
	
		
			
				|  |  | -        let mut len = write_record_header(
 | 
	
		
			
				|  |  | +        let len = write_record_header(
 | 
	
		
			
				|  |  |              &mut buf,
 | 
	
		
			
				|  |  |              "test",
 | 
	
		
			
				|  |  |              aya_log_common::Level::Info,
 | 
	
	
		
			
				|  | @@ -327,14 +492,18 @@ mod test {
 | 
	
		
			
				|  |  |              123,
 | 
	
		
			
				|  |  |              args,
 | 
	
		
			
				|  |  |          )?;
 | 
	
		
			
				|  |  | -        len += write_record_message(&mut buf[len..], msg)?;
 | 
	
		
			
				|  |  |          Ok((len, buf))
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[test]
 | 
	
		
			
				|  |  |      fn test_str() {
 | 
	
		
			
				|  |  |          testing_logger::setup();
 | 
	
		
			
				|  |  | -        let (_, input) = new_log("test", 0).unwrap();
 | 
	
		
			
				|  |  | +        let (len, mut input) = new_log(1).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        "test"
 | 
	
		
			
				|  |  | +            .write(&mut input[len..])
 | 
	
		
			
				|  |  | +            .expect("could not write to the buffer");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          let logger = logger();
 | 
	
		
			
				|  |  |          let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  |          testing_logger::validate(|captured_logs| {
 | 
	
	
		
			
				|  | @@ -347,9 +516,13 @@ mod test {
 | 
	
		
			
				|  |  |      #[test]
 | 
	
		
			
				|  |  |      fn test_str_with_args() {
 | 
	
		
			
				|  |  |          testing_logger::setup();
 | 
	
		
			
				|  |  | -        let (len, mut input) = new_log("hello {}", 1).unwrap();
 | 
	
		
			
				|  |  | -        let name = "test";
 | 
	
		
			
				|  |  | -        (*name).write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(2).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "hello "
 | 
	
		
			
				|  |  | +            .write(&mut input[len..])
 | 
	
		
			
				|  |  | +            .expect("could not write to the buffer");
 | 
	
		
			
				|  |  | +        "test".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          let logger = logger();
 | 
	
		
			
				|  |  |          let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  |          testing_logger::validate(|captured_logs| {
 | 
	
	
		
			
				|  | @@ -358,4 +531,122 @@ mod test {
 | 
	
		
			
				|  |  |              assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_default() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "default hint: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::Default.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        14.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "default hint: 14");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_lower_hex() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "lower hex: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::LowerHex.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        200.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "lower hex: c8");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_upper_hex() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "upper hex: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::UpperHex.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        200.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "upper hex: C8");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_ipv4() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "ipv4: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::Ipv4.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        // 10.0.0.1 as u32
 | 
	
		
			
				|  |  | +        167772161u32.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "ipv4: 10.0.0.1");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_ipv6_arr_u8_len_16() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "ipv6: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::Ipv6.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        // 2001:db8::1:1 as byte array
 | 
	
		
			
				|  |  | +        let ipv6_arr: [u8; 16] = [
 | 
	
		
			
				|  |  | +            0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
 | 
	
		
			
				|  |  | +            0x00, 0x01,
 | 
	
		
			
				|  |  | +        ];
 | 
	
		
			
				|  |  | +        ipv6_arr.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    #[test]
 | 
	
		
			
				|  |  | +    fn test_display_hint_ipv6_arr_u16_len_8() {
 | 
	
		
			
				|  |  | +        testing_logger::setup();
 | 
	
		
			
				|  |  | +        let (mut len, mut input) = new_log(3).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len += "ipv6: ".write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        len += DisplayHint::Ipv6.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +        // 2001:db8::1:1 as u16 array
 | 
	
		
			
				|  |  | +        let ipv6_arr: [u16; 8] = [
 | 
	
		
			
				|  |  | +            0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001,
 | 
	
		
			
				|  |  | +        ];
 | 
	
		
			
				|  |  | +        ipv6_arr.write(&mut input[len..]).unwrap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let logger = logger();
 | 
	
		
			
				|  |  | +        let _ = log_buf(&input, logger);
 | 
	
		
			
				|  |  | +        testing_logger::validate(|captured_logs| {
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs.len(), 1);
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].body, "ipv6: 2001:db8::1:1");
 | 
	
		
			
				|  |  | +            assert_eq!(captured_logs[0].level, Level::Info);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |