comparison src/logging.rs @ 159:634cd5f2ac8b

Separate logging into its own trait apart from the rest of PAM.
author Paul Fisher <paul@pfish.zone>
date Sat, 12 Jul 2025 18:16:18 -0400
parents 0099f2f79f86
children e27c5c667a5a
comparison
equal deleted inserted replaced
158:d5b7b28d754e 159:634cd5f2ac8b
12 //! dynamic libraries, and `log` doesn't work across dynamic linking boundaries. 12 //! dynamic libraries, and `log` doesn't work across dynamic linking boundaries.
13 //! 13 //!
14 //! A `PamShared` implementation may still use the `log` crate on the backend, 14 //! A `PamShared` implementation may still use the `log` crate on the backend,
15 //! and may even itself implement `log::Log`, but that interface is not exposed 15 //! and may even itself implement `log::Log`, but that interface is not exposed
16 //! to the generic PAM user. 16 //! to the generic PAM user.
17
18 use crate::_doc::{man7, manbsd};
19 use std::fmt;
20
21 /// A trait for logging.
22 pub trait Logger {
23 /// Logs something via this PAM handle.
24 ///
25 /// You probably want to use one of the logging macros,
26 /// like [`error!`](crate::error!),
27 /// [`warn!`](crate::warn!),
28 /// [`info!`](crate::info!),
29 /// or [`debug!`](crate::debug!).
30 ///
31 /// In most PAM implementations, this will go to syslog.
32 /// See [Linux-PAM's `pam_syslog`][man7] or
33 /// [OpenPAM's `openpam_log`][manbsd] for more details.
34 ///
35 /// # Example
36 ///
37 /// ```no_run
38 /// # use nonstick::PamShared;
39 /// use nonstick::logging::Level;
40 /// use nonstick::location;
41 /// # fn _test(pam_hdl: impl PamShared) {
42 /// # let delay_ms = 100;
43 /// # let url = "https://zombo.com";
44 /// // Usually, instead of calling this manually, just use the macros.
45 /// nonstick::error!(pam_hdl, "something bad happened!");
46 /// nonstick::warn!(pam_hdl, "loading information took {delay_ms} ms");
47 /// nonstick::info!(pam_hdl, "using network backend");
48 /// nonstick::debug!(pam_hdl, "sending GET request to {url}");
49 /// // But if you really want to, you can call this yourself:
50 /// pam_hdl.log(Level::Warn, location!(), format_args!("this is unnecessarily verbose"));
51 /// # }
52 /// ```
53 #[doc = man7!(3 pam_syslog)]
54 #[doc = manbsd!(3 openpam_log)]
55 fn log(&self, level: Level, loc: Location<'_>, entry: fmt::Arguments);
56 }
17 57
18 /// An entry to be added to the log. 58 /// An entry to be added to the log.
19 /// 59 ///
20 /// The levels are in descending order of importance and correspond roughly 60 /// The levels are in descending order of importance and correspond roughly
21 /// to the similarly-named levels in the `log` crate. 61 /// to the similarly-named levels in the `log` crate.
165 use std::cell::RefCell; 205 use std::cell::RefCell;
166 use std::fmt; 206 use std::fmt;
167 207
168 #[test] 208 #[test]
169 fn test_logging() { 209 fn test_logging() {
170 struct Logger(RefCell<Vec<(Level, String)>>); 210 struct TestLog(RefCell<Vec<(Level, String)>>);
171 211
172 impl Logger { 212 impl Logger for TestLog {
173 fn log(&self, level: Level, _: Location<'_>, text: fmt::Arguments) { 213 fn log(&self, level: Level, _: Location<'_>, text: fmt::Arguments) {
174 self.0.borrow_mut().push((level, text.to_string())) 214 self.0.borrow_mut().push((level, text.to_string()))
175 } 215 }
176 } 216 }
177 217
178 let logger = Logger(Default::default()); 218 let logger = TestLog(Default::default());
179 219
180 let something = Level::Error; 220 let something = Level::Error;
181 error!(logger, "here is another thing: {}", 99); 221 error!(logger, "here is another thing: {}", 99);
182 warn!(logger, "watch out!"); 222 warn!(logger, "watch out!");
183 info!(logger, "here is some info: {info}", info = "information"); 223 info!(logger, "here is some info: {info}", info = "information");