Skip to content

Commit 1ce2119

Browse files
sdroegeMatteo Biggio
authored andcommitted
Merge pull request gtk-rs#595 from jf2048/structured-logging
Structured Logging
1 parent d6a9cd1 commit 1ce2119

File tree

9 files changed

+1093
-127
lines changed

9 files changed

+1093
-127
lines changed

glib-macros/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,20 @@ pub fn variant_derive(input: TokenStream) -> TokenStream {
734734
let input = parse_macro_input!(input as DeriveInput);
735735
variant_derive::impl_variant(input)
736736
}
737+
738+
#[proc_macro]
739+
pub fn cstr_bytes(item: TokenStream) -> TokenStream {
740+
syn::parse::Parser::parse2(
741+
|stream: syn::parse::ParseStream<'_>| {
742+
let literal = stream.parse::<syn::LitStr>()?;
743+
stream.parse::<syn::parse::Nothing>()?;
744+
let bytes = std::ffi::CString::new(literal.value())
745+
.map_err(|e| syn::Error::new_spanned(&literal, format!("{}", e)))?
746+
.into_bytes_with_nul();
747+
let bytes = proc_macro2::Literal::byte_string(&bytes);
748+
Ok(quote::quote! { #bytes }.into())
749+
},
750+
item.into(),
751+
)
752+
.unwrap_or_else(|e| e.into_compile_error().into())
753+
}

glib/Gir.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ generate = [
2020
"GLib.KeyFileError",
2121
"GLib.KeyFileFlags",
2222
"GLib.LogLevelFlags",
23+
"GLib.LogWriterOutput",
2324
"GLib.MainContextFlags",
2425
"GLib.OptionArg",
2526
"GLib.OptionFlags",

glib/src/auto/enums.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,64 @@ impl ErrorDomain for KeyFileError {
354354
}
355355
}
356356

357+
#[cfg(any(feature = "v2_50", feature = "dox"))]
358+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
359+
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
360+
#[non_exhaustive]
361+
#[doc(alias = "GLogWriterOutput")]
362+
pub enum LogWriterOutput {
363+
#[doc(alias = "G_LOG_WRITER_HANDLED")]
364+
Handled,
365+
#[doc(alias = "G_LOG_WRITER_UNHANDLED")]
366+
Unhandled,
367+
#[doc(hidden)]
368+
__Unknown(i32),
369+
}
370+
371+
#[cfg(any(feature = "v2_50", feature = "dox"))]
372+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
373+
impl fmt::Display for LogWriterOutput {
374+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
375+
write!(
376+
f,
377+
"LogWriterOutput::{}",
378+
match *self {
379+
Self::Handled => "Handled",
380+
Self::Unhandled => "Unhandled",
381+
_ => "Unknown",
382+
}
383+
)
384+
}
385+
}
386+
387+
#[cfg(any(feature = "v2_50", feature = "dox"))]
388+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
389+
#[doc(hidden)]
390+
impl IntoGlib for LogWriterOutput {
391+
type GlibType = ffi::GLogWriterOutput;
392+
393+
fn into_glib(self) -> ffi::GLogWriterOutput {
394+
match self {
395+
Self::Handled => ffi::G_LOG_WRITER_HANDLED,
396+
Self::Unhandled => ffi::G_LOG_WRITER_UNHANDLED,
397+
Self::__Unknown(value) => value,
398+
}
399+
}
400+
}
401+
402+
#[cfg(any(feature = "v2_50", feature = "dox"))]
403+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
404+
#[doc(hidden)]
405+
impl FromGlib<ffi::GLogWriterOutput> for LogWriterOutput {
406+
unsafe fn from_glib(value: ffi::GLogWriterOutput) -> Self {
407+
match value {
408+
ffi::G_LOG_WRITER_HANDLED => Self::Handled,
409+
ffi::G_LOG_WRITER_UNHANDLED => Self::Unhandled,
410+
value => Self::__Unknown(value),
411+
}
412+
}
413+
}
414+
357415
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
358416
#[non_exhaustive]
359417
#[doc(alias = "GOptionArg")]

glib/src/auto/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pub use self::enums::ChecksumType;
3535
pub use self::enums::DateMonth;
3636
pub use self::enums::DateWeekday;
3737
pub use self::enums::KeyFileError;
38+
#[cfg(any(feature = "v2_50", feature = "dox"))]
39+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
40+
pub use self::enums::LogWriterOutput;
3841
pub use self::enums::OptionArg;
3942
pub use self::enums::SeekType;
4043
pub use self::enums::TimeType;

glib/src/bridged_logging.rs

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ pub enum GlibLoggerFormat {
1919
LineAndFile,
2020
// rustdoc-stripper-ignore-next
2121
/// A logger using glib structured logging. Structured logging is available
22-
/// only on features `v2_56` and later.
23-
#[cfg(any(feature = "v2_56", feature = "dox"))]
22+
/// only on features `v2_50` and later.
23+
#[cfg(any(feature = "v2_50", feature = "dox"))]
24+
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_50")))]
2425
Structured,
2526
}
2627

@@ -104,15 +105,15 @@ impl GlibLogger {
104105
Self { format, domain }
105106
}
106107

107-
fn level_to_glib(level: rs_log::Level) -> crate::ffi::GLogLevelFlags {
108+
fn level_to_glib(level: rs_log::Level) -> crate::LogLevel {
108109
match level {
109110
// Errors are mapped to critical to avoid automatic termination
110-
rs_log::Level::Error => crate::ffi::G_LOG_LEVEL_CRITICAL,
111-
rs_log::Level::Warn => crate::ffi::G_LOG_LEVEL_WARNING,
112-
rs_log::Level::Info => crate::ffi::G_LOG_LEVEL_INFO,
113-
rs_log::Level::Debug => crate::ffi::G_LOG_LEVEL_DEBUG,
111+
rs_log::Level::Error => crate::LogLevel::Critical,
112+
rs_log::Level::Warn => crate::LogLevel::Warning,
113+
rs_log::Level::Info => crate::LogLevel::Info,
114+
rs_log::Level::Debug => crate::LogLevel::Debug,
114115
// There is no equivalent to trace level in glib
115-
rs_log::Level::Trace => crate::ffi::G_LOG_LEVEL_DEBUG,
116+
rs_log::Level::Trace => crate::LogLevel::Debug,
116117
}
117118
}
118119

@@ -121,16 +122,14 @@ impl GlibLogger {
121122
unsafe {
122123
crate::ffi::g_log(
123124
domain.to_glib_none().0,
124-
GlibLogger::level_to_glib(level),
125+
GlibLogger::level_to_glib(level).into_glib(),
125126
b"%s\0".as_ptr() as *const _,
126127
ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(message).0,
127128
);
128129
}
129130
}
130131

131-
#[cfg(any(feature = "v2_56", feature = "dox"))]
132-
#[cfg_attr(feature = "dox", doc(cfg(feature = "v2_56")))]
133-
#[doc(alias = "g_log_structured_standard")]
132+
#[cfg(any(feature = "v2_50", feature = "dox"))]
134133
fn write_log_structured(
135134
domain: Option<&str>,
136135
level: rs_log::Level,
@@ -139,24 +138,19 @@ impl GlibLogger {
139138
func: Option<&str>,
140139
message: &str,
141140
) {
142-
let line_str = line.map(|l| l.to_string());
141+
let line = line.map(|l| l.to_string());
142+
let line = line.as_ref().map(|s| s.as_str());
143143

144-
let domain = domain.unwrap_or("default");
145-
let file = file.unwrap_or("<unknown file>");
146-
let line_str = line_str.unwrap_or_else(|| String::from("<unknown line>"));
147-
let func = func.unwrap_or("<unknown module path>");
148-
149-
unsafe {
150-
crate::ffi::g_log_structured_standard(
151-
domain.to_glib_none().0,
152-
GlibLogger::level_to_glib(level),
153-
file.to_glib_none().0,
154-
line_str.to_glib_none().0,
155-
func.to_glib_none().0,
156-
b"%s\0".as_ptr() as *const _,
157-
ToGlibPtr::<*const std::os::raw::c_char>::to_glib_none(message).0,
158-
);
159-
}
144+
crate::log_structured!(
145+
domain.unwrap_or("default"),
146+
GlibLogger::level_to_glib(level),
147+
{
148+
"CODE_FILE" => file.unwrap_or("<unknown file>");
149+
"CODE_LINE" => line.unwrap_or("<unknown line>");
150+
"CODE_FUNC" => func.unwrap_or("<unknown module path>");
151+
"MESSAGE" => message;
152+
}
153+
);
160154
}
161155
}
162156

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

179173
match self.format {
180174
GlibLoggerFormat::Plain => {
181-
let s = format!("{}", record.args());
182-
GlibLogger::write_log(domain, record.level(), &s)
175+
let args = record.args();
176+
if let Some(s) = args.as_str() {
177+
GlibLogger::write_log(domain, record.level(), s);
178+
} else {
179+
GlibLogger::write_log(domain, record.level(), &args.to_string());
180+
}
183181
}
184182
GlibLoggerFormat::LineAndFile => {
185-
let s = match (record.file(), record.line()) {
186-
(Some(file), Some(line)) => format!("{}:{}: {}", file, line, record.args()),
187-
(Some(file), None) => format!("{}: {}", file, record.args()),
188-
_ => format!("{}", record.args()),
183+
match (record.file(), record.line()) {
184+
(Some(file), Some(line)) => {
185+
let s = format!("{}:{}: {}", file, line, record.args());
186+
GlibLogger::write_log(domain, record.level(), &s);
187+
}
188+
(Some(file), None) => {
189+
let s = format!("{}: {}", file, record.args());
190+
GlibLogger::write_log(domain, record.level(), &s);
191+
}
192+
_ => {
193+
let args = record.args();
194+
if let Some(s) = args.as_str() {
195+
GlibLogger::write_log(domain, record.level(), s);
196+
} else {
197+
GlibLogger::write_log(domain, record.level(), &args.to_string());
198+
}
199+
}
189200
};
190-
191-
GlibLogger::write_log(domain, record.level(), &s);
192201
}
193-
#[cfg(any(feature = "v2_56", feature = "dox"))]
202+
#[cfg(any(feature = "v2_50", feature = "dox"))]
194203
GlibLoggerFormat::Structured => {
195-
GlibLogger::write_log_structured(
196-
domain,
197-
record.level(),
198-
record.file(),
199-
record.line(),
200-
record.module_path(),
201-
&format!("{}", record.args()),
202-
);
204+
let args = record.args();
205+
if let Some(s) = args.as_str() {
206+
GlibLogger::write_log_structured(
207+
domain,
208+
record.level(),
209+
record.file(),
210+
record.line(),
211+
record.module_path(),
212+
s,
213+
);
214+
} else {
215+
GlibLogger::write_log_structured(
216+
domain,
217+
record.level(),
218+
record.file(),
219+
record.line(),
220+
record.module_path(),
221+
&args.to_string(),
222+
);
223+
}
203224
}
204225
};
205226
}

0 commit comments

Comments
 (0)