comparison src/logging.rs @ 157:0099f2f79f86

Switch logging interface to accept fmt::Arguments. This means that we don't have to format arguments eagerly when logging; an implementation could choose to discard them if it wanted to, avoiding allocations and expensive format calls.
author Paul Fisher <paul@pfish.zone>
date Wed, 09 Jul 2025 16:59:30 -0400
parents ab8020566cd9
children 634cd5f2ac8b
comparison
equal deleted inserted replaced
156:66e662cde087 157:0099f2f79f86
23 /// Their values are ordered monotonically, either increasing or decreasing, 23 /// Their values are ordered monotonically, either increasing or decreasing,
24 /// depending upon the implementation. 24 /// depending upon the implementation.
25 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 25 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
26 pub enum Level { 26 pub enum Level {
27 Error, 27 Error,
28 Warning, 28 Warn,
29 Info, 29 Info,
30 Debug, 30 Debug,
31 } 31 }
32 32
33 /// The location of a log entry. Use [`location!`](crate::location!) to create this. 33 /// The location of a log entry. Use [`location!`](crate::location!) to create this.
62 /// Here's the guts of the logger thingy. You shouldn't be using this! 62 /// Here's the guts of the logger thingy. You shouldn't be using this!
63 #[doc(hidden)] 63 #[doc(hidden)]
64 #[macro_export] 64 #[macro_export]
65 macro_rules! __log_internal { 65 macro_rules! __log_internal {
66 ($handle:expr, $level:ident, $($arg:tt)+) => { 66 ($handle:expr, $level:ident, $($arg:tt)+) => {
67 $handle.log($crate::logging::Level::$level, $crate::location!(), &format!($($arg)+)); 67 $handle.log($crate::logging::Level::$level, $crate::location!(), format_args!($($arg)+));
68 } 68 }
69 } 69 }
70 70
71 /// Ugly, hacky macro to get the current function name. 71 /// Ugly, hacky macro to get the current function name.
72 /// 72 ///
120 /// // Will log a message like "loading took too long: 495 ms" 120 /// // Will log a message like "loading took too long: 495 ms"
121 /// // at WARN level on syslog. 121 /// // at WARN level on syslog.
122 /// # } 122 /// # }
123 /// ``` 123 /// ```
124 #[macro_export] 124 #[macro_export]
125 macro_rules! warn { ($handle:expr, $($arg:tt)+) => { $crate::__log_internal!($handle, Warning, $($arg)+);}} 125 macro_rules! warn { ($handle:expr, $($arg:tt)+) => { $crate::__log_internal!($handle, Warn, $($arg)+);}}
126 126
127 /// Logs a message at info level via the given PAM handle. 127 /// Logs a message at info level via the given PAM handle.
128 /// 128 ///
129 /// This supports `format!`-style formatting. 129 /// This supports `format!`-style formatting.
130 /// 130 ///
161 161
162 #[cfg(test)] 162 #[cfg(test)]
163 mod tests { 163 mod tests {
164 use super::*; 164 use super::*;
165 use std::cell::RefCell; 165 use std::cell::RefCell;
166 use std::fmt;
166 167
167 #[test] 168 #[test]
168 fn test_logging() { 169 fn test_logging() {
169 struct Logger(RefCell<Vec<(Level, String)>>); 170 struct Logger(RefCell<Vec<(Level, String)>>);
170 171
171 impl Logger { 172 impl Logger {
172 fn log(&self, level: Level, _: Location<'_>, text: &str) { 173 fn log(&self, level: Level, _: Location<'_>, text: fmt::Arguments) {
173 self.0.borrow_mut().push((level, text.to_owned())) 174 self.0.borrow_mut().push((level, text.to_string()))
174 } 175 }
175 } 176 }
176 177
177 let logger = Logger(Default::default()); 178 let logger = Logger(Default::default());
178 179
185 let logged = logger.0.into_inner(); 186 let logged = logger.0.into_inner();
186 187
187 assert_eq!( 188 assert_eq!(
188 vec![ 189 vec![
189 (Level::Error, "here is another thing: 99".to_owned()), 190 (Level::Error, "here is another thing: 99".to_owned()),
190 (Level::Warning, "watch out!".to_owned()), 191 (Level::Warn, "watch out!".to_owned()),
191 (Level::Info, "here is some info: information".to_owned()), 192 (Level::Info, "here is some info: information".to_owned()),
192 (Level::Debug, "here is something: Error".to_owned()), 193 (Level::Debug, "here is something: Error".to_owned()),
193 ], 194 ],
194 logged 195 logged
195 ); 196 );