pw_log/
pw_log.rs

1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15//! `pw_log` is an extensible logging system that can delegate to
16//! pre-existing logging APIs without upstream changes.
17//!
18//! Clients of `pw_log` simply import and use the logging API, and
19//! log invocations will be handled by the provided logging backend.
20//!
21//! This flexibility is accomplished using Pigweed's
22//! [facade pattern](https://pigweed.dev/docs/facades.html),
23//! which uses build-system redirection to forward log invocations to the
24//! configured backend implementation.
25//!
26//! ```
27//! use pw_log::{log, info, LogLevel};
28//!
29//! log!(LogLevel::Info, "Thank you for signing up for Log Facts!");
30//! info!("Log Fact: Logs can be either {}, {}, or {} sawn.",
31//!   "flat" as &str, "quarter" as &str, "rift" as &str);
32//! ```
33//!
34//! Today `printf` style format strings are well supported with Rust
35//! [`core::fmt`]/`println!()` style strings partially supported
36//! ([b/311232607](https://issues.pigweed.dev/issues/311232607)).
37//!
38//! Currently, when using a `stable` toolchain, "untyped" arguments (i.e.
39//! `{}` style) need to be in the form of an as-cast.  Users with nightly
40//! toolchains can enable the `nightly_tait` feature to remove this restriction.
41//!
42//! TODO: <pwbug.dev/311266298> - Document `pw_log`'s backend API.
43//!
44//! TODO: <pwbug.dev/311232605> - Document how to configure facade backends.
45#![cfg_attr(not(feature = "std"), no_std)]
46#![deny(missing_docs)]
47
48pub use pw_log_backend_api::LogLevel;
49
50// Re-export dependencies of `pw_log` macros to be accessed via `$crate::__private`.
51#[doc(hidden)]
52pub mod __private {
53    pub use pw_log_backend::{pw_log_backend, pw_logf_backend};
54
55    pub use crate::*;
56}
57
58/// Emit a log message using `core::fmt` format string semantics.
59///
60/// `log` takes a [`LogLevel`], a `core::fmt` style format string, and necessary
61/// arguments to that string and emits a log message to the logging backend.
62///
63/// ```
64/// use pw_log::{log, LogLevel};
65///
66/// log!(LogLevel::Info, "Log fact: A {} log has a Janka hardness of {} lbf.",
67///      "Spruce Pine" as &str, 700 as i32);
68/// ```
69#[macro_export]
70macro_rules! log {
71  ($log_level:expr, $format_string:literal $(,)?) => {{
72    use $crate::__private as __pw_log_crate;
73    $crate::__private::pw_log_backend!($log_level, $format_string)
74  }};
75
76  ($log_level:expr, $format_string:literal, $($args:expr),* $(,)?) => {{
77    use $crate::__private as __pw_log_crate;
78    $crate::__private::pw_log_backend!($log_level, $format_string, $($args),*)
79  }};
80}
81
82/// Emit a log message using `printf` format string semantics.
83///
84/// `logf` takes a [`LogLevel`], a `printf` style format string, and necessary
85/// arguments to that string and emits a log message to the logging backend.
86///
87/// ```
88/// use pw_log::{logf, LogLevel};
89///
90/// logf!(LogLevel::Info, "Log fact: A %s log has a Janka hardness of %d lbf.",
91///     "Spruce Pine", 700);
92/// ```
93#[macro_export]
94macro_rules! logf {
95  ($log_level:expr, $format_string:literal $(,)?) => {{
96    use $crate::__private as __pw_log_crate;
97    $crate::__private::pw_logf_backend!($log_level, $format_string)
98  }};
99
100  ($log_level:expr, $format_string:literal, $($args:expr),* $(,)?) => {{
101    use $crate::__private as __pw_log_crate;
102    $crate::__private::pw_logf_backend!($log_level, $format_string, $($args),*)
103  }};
104}
105
106/// Deprecated alias for [`logf!`].
107#[macro_export]
108macro_rules! pw_logf {
109  ($($args:expr),* $(,)?) => {{
110    logf!($($args),*)
111  }}
112}
113
114/// Emit a debug level log message using `core:fmt` format string semantics.
115///
116/// ```
117/// use pw_log::debug;
118///
119/// debug!("Log Fact: The American toy Lincoln Logs were inspired by the {} in {}.",
120///     "Imperial Hotel" as &str, "Tokyo" as &str);
121/// ```
122#[macro_export]
123macro_rules! debug {
124  ($($args:expr),* $(,)?) => {{
125    use $crate::__private as __pw_log_crate;
126    __pw_log_crate::log!(__pw_log_crate::LogLevel::Debug, $($args),*)
127  }};
128}
129
130/// Emit a debug level log message using `printf` format string semantics.
131///
132/// ```
133/// use pw_log::debugf;
134///
135/// debugf!("Log Fact: The American toy Lincoln Logs were inspired by the %s in %s.",
136///     "Imperial Hotel", "Tokyo");
137/// ```
138#[macro_export]
139macro_rules! debugf {
140  ($($args:expr),* $(,)?) => {{
141    use $crate::__private as __pw_log_crate;
142    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Debug, $($args),*)
143  }};
144}
145
146/// Deprecated alias for [`debugf!`].
147#[macro_export]
148macro_rules! pw_log_debugf {
149  ($($args:expr),* $(,)?) => {{
150    debugf!($($args),*)
151  }}
152}
153
154/// Emit an info level log message using `core:fmt` format string semantics.
155///
156/// ```
157/// use pw_log::info;
158///
159/// info!(
160///     "Log Fact: The American president Abraham Lincoln (born {:x}) once lived in a log cabin.",
161///     0x1809 as u32);
162/// ```
163#[macro_export]
164macro_rules! info {
165  ($($args:expr),* $(,)?) => {{
166    use $crate::__private as __pw_log_crate;
167    __pw_log_crate::log!(__pw_log_crate::LogLevel::Info, $($args),*)
168  }};
169}
170
171/// Emit an info level log message using `printf` format string semantics.
172///
173/// ```
174/// use pw_log::infof;
175///
176/// infof!(
177///     "Log Fact: The American president Abraham Lincoln (born %x) once lived in a log cabin.",
178/// 0x1809);
179/// ```
180#[macro_export]
181macro_rules! infof {
182  ($($args:expr),* $(,)?) => {{
183    use $crate::__private as __pw_log_crate;
184    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Info, $($args),*)
185  }};
186}
187
188/// Deprecated alias for [`infof!`].
189#[macro_export]
190macro_rules! pw_log_infof {
191  ($($args:expr),* $(,)?) => {{
192    infof!($($args),*)
193  }}
194}
195
196/// Emit a warn level log message using `core::fmt` format string semantics.
197///
198/// ```
199/// use pw_log::warn;
200///
201/// warn!(
202///     "Log Fact: Made from a log, an {} year old dugout canoe is the oldest discovered boat in {}.",
203///     8000 as i32, "Africa" as &str);
204/// ```
205#[macro_export]
206macro_rules! warn {
207  ($($args:expr),* $(,)?) => {{
208    use $crate::__private as __pw_log_crate;
209    __pw_log_crate::log!(__pw_log_crate::LogLevel::Warn, $($args),*)
210  }};
211}
212
213/// Emit a warn level log message using `printf` format string semantics.
214///
215/// ```
216/// use pw_log::warnf;
217///
218/// warnf!(
219///     "Log Fact: Made from a log, an %d year old dugout canoe is the oldest discovered boat in %s.",
220///     8000, "Africa");
221/// ```
222#[macro_export]
223macro_rules! warnf {
224  ($($args:expr),* $(,)?) => {{
225    use $crate::__private as __pw_log_crate;
226    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Warn, $($args),*)
227  }};
228}
229
230/// Deprecated alias for [`warnf!`].
231#[macro_export]
232macro_rules! pw_log_warnf {
233  ($($args:expr),* $(,)?) => {{
234    warnf!($($args),*)
235  }}
236}
237
238/// Emit an error level log message using `core::fmt` format string semantics.
239///
240/// ```
241/// use pw_log::error;
242///
243/// error!(
244///     "Log Fact: Before saws were invented, the {} was used prepare logs for use.",
245///     "adze" as &str);
246/// ```
247#[macro_export]
248macro_rules! error {
249  ($($args:expr),* $(,)?) => {{
250    use $crate::__private as __pw_log_crate;
251    __pw_log_crate::log!(__pw_log_crate::LogLevel::Error, $($args),*)
252  }};
253}
254
255/// Emit an error level log message using `printf` format string semantics.
256///
257/// ```
258/// use pw_log::errorf;
259///
260/// errorf!(
261///     "Log Fact: Before saws were invented, the %s was used prepare logs for use.",
262///     "adze");
263/// ```
264#[macro_export]
265macro_rules! errorf {
266  ($($args:expr),* $(,)?) => {{
267    use $crate::__private as __pw_log_crate;
268    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Error, $($args),*)
269  }};
270}
271
272/// Deprecated alias for [`errorf!`].
273#[macro_export]
274macro_rules! pw_log_errorf {
275  ($($args:expr),* $(,)?) => {{
276    errorf!($($args),*)
277  }}
278}
279
280/// Emit a critical level log message using `core::fmt` format string semantics.
281///
282/// ```
283/// use pw_log::critical;
284///
285/// critical!(
286///     "Log Fact: Until the {}th century, all ships' masts were made from a single log.",
287///     19 as u32);
288/// ```
289#[macro_export]
290macro_rules! critical {
291  ($($args:expr),* $(,)?) => {{
292    use $crate::__private as __pw_log_crate;
293    __pw_log_crate::log!(__pw_log_crate::LogLevel::Critical, $($args),*)
294  }};
295}
296
297/// Emit a critical level log message using `printf` format string semantics.
298///
299/// ```
300/// use pw_log::criticalf;
301///
302/// criticalf!(
303///     "Log Fact: Until the %dth century, all ships' masts were made from a single log.",
304///     19);
305/// ```
306#[macro_export]
307macro_rules! criticalf {
308  ($($args:expr),* $(,)?) => {{
309    use $crate::__private as __pw_log_crate;
310    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Critical, $($args),*)
311  }};
312}
313
314/// Deprecated alias for [`criticalf!`].
315#[macro_export]
316macro_rules! pw_log_criticalf {
317  ($($args:expr),* $(,)?) => {{
318    criticalf!($($args),*)
319  }}
320}
321
322/// Emit a fatal level log message using `core::fmt` format string semantics.
323///
324/// *Note*: `fatal` only emits a log message and does not cause a `panic!()`
325///
326/// ```
327/// use pw_log::fatal;
328///
329/// fatal!("Log Fact: All out of log facts! Timber!");
330/// ```
331#[macro_export]
332macro_rules! fatal {
333  ($($args:expr),* $(,)?) => {{
334    use $crate::__private as __pw_log_crate;
335    __pw_log_crate::log!(__pw_log_crate::LogLevel::Fatal, $($args),*)
336  }};
337}
338
339/// Emit a fatal level log message using `printf` format string semantics.
340///
341/// *Note*: `fatalf` only emits a log message and does not cause a `panic!()`
342///
343/// ```
344/// use pw_log::fatalf;
345///
346/// fatalf!("Log Fact: All out of log facts! Timber!");
347/// ```
348#[macro_export]
349macro_rules! fatalf {
350  ($($args:expr),* $(,)?) => {{
351    use $crate::__private as __pw_log_crate;
352    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Fatal, $($args),*)
353  }};
354}
355
356/// Deprecated alias for [`fatalf!`].
357#[macro_export]
358macro_rules! pw_log_fatalf {
359  ($($args:expr),* $(,)?) => {{
360    fatalf!($($args),*)
361  }}
362}
363
364#[cfg(test)]
365mod tests {
366    // TODO(b/311262163): Add infrastructure for testing behavior of `pw_log` API.
367    // The syntax of that API is verified through doctests.
368}