Skip to content

Commit

Permalink
Merge pull request gtk-rs#595 from jf2048/structured-logging
Browse files Browse the repository at this point in the history
Structured Logging
  • Loading branch information
sdroege authored and Matteo Biggio committed Mar 14, 2022
1 parent d6a9cd1 commit 1ce2119
Show file tree
Hide file tree
Showing 9 changed files with 1,093 additions and 127 deletions.
17 changes: 17 additions & 0 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,20 @@ pub fn variant_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
variant_derive::impl_variant(input)
}

#[proc_macro]
pub fn cstr_bytes(item: TokenStream) -> TokenStream {
syn::parse::Parser::parse2(
|stream: syn::parse::ParseStream<'_>| {
let literal = stream.parse::<syn::LitStr>()?;
stream.parse::<syn::parse::Nothing>()?;
let bytes = std::ffi::CString::new(literal.value())
.map_err(|e| syn::Error::new_spanned(&literal, format!("{}", e)))?
.into_bytes_with_nul();
let bytes = proc_macro2::Literal::byte_string(&bytes);
Ok(quote::quote! { #bytes }.into())
},
item.into(),
)
.unwrap_or_else(|e| e.into_compile_error().into())
}
1 change: 1 addition & 0 deletions glib/Gir.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ generate = [
"GLib.KeyFileError",
"GLib.KeyFileFlags",
"GLib.LogLevelFlags",
"GLib.LogWriterOutput",
"GLib.MainContextFlags",
"GLib.OptionArg",
"GLib.OptionFlags",
Expand Down
58 changes: 58 additions & 0 deletions glib/src/auto/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,64 @@ impl ErrorDomain for KeyFileError {
}
}

#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GLogWriterOutput")]
pub enum LogWriterOutput {
#[doc(alias = "G_LOG_WRITER_HANDLED")]
Handled,
#[doc(alias = "G_LOG_WRITER_UNHANDLED")]
Unhandled,
#[doc(hidden)]
__Unknown(i32),
}

#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
impl fmt::Display for LogWriterOutput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"LogWriterOutput::{}",
match *self {
Self::Handled => "Handled",
Self::Unhandled => "Unhandled",
_ => "Unknown",
}
)
}
}

#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
#[doc(hidden)]
impl IntoGlib for LogWriterOutput {
type GlibType = ffi::GLogWriterOutput;

fn into_glib(self) -> ffi::GLogWriterOutput {
match self {
Self::Handled => ffi::G_LOG_WRITER_HANDLED,
Self::Unhandled => ffi::G_LOG_WRITER_UNHANDLED,
Self::__Unknown(value) => value,
}
}
}

#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
#[doc(hidden)]
impl FromGlib<ffi::GLogWriterOutput> for LogWriterOutput {
unsafe fn from_glib(value: ffi::GLogWriterOutput) -> Self {
match value {
ffi::G_LOG_WRITER_HANDLED => Self::Handled,
ffi::G_LOG_WRITER_UNHANDLED => Self::Unhandled,
value => Self::__Unknown(value),
}
}
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GOptionArg")]
Expand Down
3 changes: 3 additions & 0 deletions glib/src/auto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pub use self::enums::ChecksumType;
pub use self::enums::DateMonth;
pub use self::enums::DateWeekday;
pub use self::enums::KeyFileError;
#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
pub use self::enums::LogWriterOutput;
pub use self::enums::OptionArg;
pub use self::enums::SeekType;
pub use self::enums::TimeType;
Expand Down
113 changes: 67 additions & 46 deletions glib/src/bridged_logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ pub enum GlibLoggerFormat {
LineAndFile,
// rustdoc-stripper-ignore-next
/// A logger using glib structured logging. Structured logging is available
/// only on features `v2_56` and later.
#[cfg(any(feature = "v2_56", feature = "dox"))]
/// only on features `v2_50` and later.
#[cfg(any(feature = "v2_50", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
Structured,
}

Expand Down Expand Up @@ -104,15 +105,15 @@ impl GlibLogger {
Self { format, domain }
}

fn level_to_glib(level: rs_log::Level) -> crate::ffi::GLogLevelFlags {
fn level_to_glib(level: rs_log::Level) -> crate::LogLevel {
match level {
// Errors are mapped to critical to avoid automatic termination
rs_log::Level::Error => crate::ffi::G_LOG_LEVEL_CRITICAL,
rs_log::Level::Warn => crate::ffi::G_LOG_LEVEL_WARNING,
rs_log::Level::Info => crate::ffi::G_LOG_LEVEL_INFO,
rs_log::Level::Debug => crate::ffi::G_LOG_LEVEL_DEBUG,
rs_log::Level::Error => crate::LogLevel::Critical,
rs_log::Level::Warn => crate::LogLevel::Warning,
rs_log::Level::Info => crate::LogLevel::Info,
rs_log::Level::Debug => crate::LogLevel::Debug,
// There is no equivalent to trace level in glib
rs_log::Level::Trace => crate::ffi::G_LOG_LEVEL_DEBUG,
rs_log::Level::Trace => crate::LogLevel::Debug,
}
}

Expand All @@ -121,16 +122,14 @@ impl GlibLogger {
unsafe {
crate::ffi::g_log(
domain.to_glib_none().0,
GlibLogger::level_to_glib(level),
GlibLogger::level_to_glib(level).into_glib(),
b"%s\0".as_ptr() as *const _,
ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(message).0,
);
}
}

#[cfg(any(feature = "v2_56", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_56")))]
#[doc(alias = "g_log_structured_standard")]
#[cfg(any(feature = "v2_50", feature = "dox"))]
fn write_log_structured(
domain: Option<&str>,
level: rs_log::Level,
Expand All @@ -139,24 +138,19 @@ impl GlibLogger {
func: Option<&str>,
message: &str,
) {
let line_str = line.map(|l| l.to_string());
let line = line.map(|l| l.to_string());
let line = line.as_ref().map(|s| s.as_str());

let domain = domain.unwrap_or("default");
let file = file.unwrap_or("<unknown file>");
let line_str = line_str.unwrap_or_else(|| String::from("<unknown line>"));
let func = func.unwrap_or("<unknown module path>");

unsafe {
crate::ffi::g_log_structured_standard(
domain.to_glib_none().0,
GlibLogger::level_to_glib(level),
file.to_glib_none().0,
line_str.to_glib_none().0,
func.to_glib_none().0,
b"%s\0".as_ptr() as *const _,
ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(message).0,
);
}
crate::log_structured!(
domain.unwrap_or("default"),
GlibLogger::level_to_glib(level),
{
"CODE_FILE" => file.unwrap_or("<unknown file>");
"CODE_LINE" => line.unwrap_or("<unknown line>");
"CODE_FUNC" => func.unwrap_or("<unknown module path>");
"MESSAGE" => message;
}
);
}
}

Expand All @@ -178,28 +172,55 @@ impl rs_log::Log for GlibLogger {

match self.format {
GlibLoggerFormat::Plain => {
let s = format!("{}", record.args());
GlibLogger::write_log(domain, record.level(), &s)
let args = record.args();
if let Some(s) = args.as_str() {
GlibLogger::write_log(domain, record.level(), s);
} else {
GlibLogger::write_log(domain, record.level(), &args.to_string());
}
}
GlibLoggerFormat::LineAndFile => {
let s = match (record.file(), record.line()) {
(Some(file), Some(line)) => format!("{}:{}: {}", file, line, record.args()),
(Some(file), None) => format!("{}: {}", file, record.args()),
_ => format!("{}", record.args()),
match (record.file(), record.line()) {
(Some(file), Some(line)) => {
let s = format!("{}:{}: {}", file, line, record.args());
GlibLogger::write_log(domain, record.level(), &s);
}
(Some(file), None) => {
let s = format!("{}: {}", file, record.args());
GlibLogger::write_log(domain, record.level(), &s);
}
_ => {
let args = record.args();
if let Some(s) = args.as_str() {
GlibLogger::write_log(domain, record.level(), s);
} else {
GlibLogger::write_log(domain, record.level(), &args.to_string());
}
}
};

GlibLogger::write_log(domain, record.level(), &s);
}
#[cfg(any(feature = "v2_56", feature = "dox"))]
#[cfg(any(feature = "v2_50", feature = "dox"))]
GlibLoggerFormat::Structured => {
GlibLogger::write_log_structured(
domain,
record.level(),
record.file(),
record.line(),
record.module_path(),
&format!("{}", record.args()),
);
let args = record.args();
if let Some(s) = args.as_str() {
GlibLogger::write_log_structured(
domain,
record.level(),
record.file(),
record.line(),
record.module_path(),
s,
);
} else {
GlibLogger::write_log_structured(
domain,
record.level(),
record.file(),
record.line(),
record.module_path(),
&args.to_string(),
);
}
}
};
}
Expand Down
Loading

0 comments on commit 1ce2119

Please sign in to comment.