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 crate::*;
54    pub use pw_log_backend::{pw_log_backend, pw_logf_backend};
55}
56
57/// Emit a log message using `core::fmt` format string semantics.
58///
59/// `log` takes a [`LogLevel`], a `core::fmt` style format string, and necessary
60/// arguments to that string and emits a log message to the logging backend.
61///
62/// ```
63/// use pw_log::{log, LogLevel};
64///
65/// log!(LogLevel::Info, "Log fact: A {} log has a Janka hardness of {} lbf.",
66///      "Spruce Pine" as &str, 700 as i32);
67/// ```
68#[macro_export]
69macro_rules! log {
70  ($log_level:expr, $format_string:literal $(,)?) => {{
71    use $crate::__private as __pw_log_crate;
72    $crate::__private::pw_log_backend!($log_level, $format_string)
73  }};
74
75  ($log_level:expr, $format_string:literal, $($args:expr),* $(,)?) => {{
76    use $crate::__private as __pw_log_crate;
77    $crate::__private::pw_log_backend!($log_level, $format_string, $($args),*)
78  }};
79}
80
81/// Emit a log message using `printf` format string semantics.
82///
83/// `logf` takes a [`LogLevel`], a `printf` style format string, and necessary
84/// arguments to that string and emits a log message to the logging backend.
85///
86/// ```
87/// use pw_log::{logf, LogLevel};
88///
89/// logf!(LogLevel::Info, "Log fact: A %s log has a Janka hardness of %d lbf.",
90///     "Spruce Pine", 700);
91/// ```
92#[macro_export]
93macro_rules! logf {
94  ($log_level:expr, $format_string:literal $(,)?) => {{
95    use $crate::__private as __pw_log_crate;
96    $crate::__private::pw_logf_backend!($log_level, $format_string)
97  }};
98
99  ($log_level:expr, $format_string:literal, $($args:expr),* $(,)?) => {{
100    use $crate::__private as __pw_log_crate;
101    $crate::__private::pw_logf_backend!($log_level, $format_string, $($args),*)
102  }};
103}
104
105/// Deprecated alias for [`logf!`].
106#[macro_export]
107macro_rules! pw_logf {
108  ($($args:expr),* $(,)?) => {{
109    logf!($($args),*)
110  }}
111}
112
113/// Emit a debug level log message using `core:fmt` format string semantics.
114///
115/// ```
116/// use pw_log::debug;
117///
118/// debug!("Log Fact: The American toy Lincoln Logs were inspired by the {} in {}.",
119///     "Imperial Hotel" as &str, "Tokyo" as &str);
120/// ```
121#[macro_export]
122macro_rules! debug {
123  ($($args:expr),* $(,)?) => {{
124    use $crate::__private as __pw_log_crate;
125    __pw_log_crate::log!(__pw_log_crate::LogLevel::Debug, $($args),*)
126  }};
127}
128
129/// Emit a debug level log message using `printf` format string semantics.
130///
131/// ```
132/// use pw_log::debugf;
133///
134/// debugf!("Log Fact: The American toy Lincoln Logs were inspired by the %s in %s.",
135///     "Imperial Hotel", "Tokyo");
136/// ```
137#[macro_export]
138macro_rules! debugf {
139  ($($args:expr),* $(,)?) => {{
140    use $crate::__private as __pw_log_crate;
141    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Debug, $($args),*)
142  }};
143}
144
145/// Deprecated alias for [`debugf!`].
146#[macro_export]
147macro_rules! pw_log_debugf {
148  ($($args:expr),* $(,)?) => {{
149    debugf!($($args),*)
150  }}
151}
152
153/// Emit an info level log message using `core:fmt` format string semantics.
154///
155/// ```
156/// use pw_log::info;
157///
158/// info!(
159///     "Log Fact: The American president Abraham Lincoln (born {:x}) once lived in a log cabin.",
160///     0x1809 as u32);
161/// ```
162#[macro_export]
163macro_rules! info {
164  ($($args:expr),* $(,)?) => {{
165    use $crate::__private as __pw_log_crate;
166    __pw_log_crate::log!(__pw_log_crate::LogLevel::Info, $($args),*)
167  }};
168}
169
170/// Emit an info level log message using `printf` format string semantics.
171///
172/// ```
173/// use pw_log::infof;
174///
175/// infof!(
176///     "Log Fact: The American president Abraham Lincoln (born %x) once lived in a log cabin.",
177/// 0x1809);
178/// ```
179#[macro_export]
180macro_rules! infof {
181  ($($args:expr),* $(,)?) => {{
182    use $crate::__private as __pw_log_crate;
183    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Info, $($args),*)
184  }};
185}
186
187/// Deprecated alias for [`infof!`].
188#[macro_export]
189macro_rules! pw_log_infof {
190  ($($args:expr),* $(,)?) => {{
191    infof!($($args),*)
192  }}
193}
194
195/// Emit a warn level log message using `core::fmt` format string semantics.
196///
197/// ```
198/// use pw_log::warn;
199///
200/// warn!(
201///     "Log Fact: Made from a log, an {} year old dugout canoe is the oldest discovered boat in {}.",
202///     8000 as i32, "Africa" as &str);
203/// ```
204#[macro_export]
205macro_rules! warn {
206  ($($args:expr),* $(,)?) => {{
207    use $crate::__private as __pw_log_crate;
208    __pw_log_crate::log!(__pw_log_crate::LogLevel::Warn, $($args),*)
209  }};
210}
211
212/// Emit a warn level log message using `printf` format string semantics.
213///
214/// ```
215/// use pw_log::warnf;
216///
217/// warnf!(
218///     "Log Fact: Made from a log, an %d year old dugout canoe is the oldest discovered boat in %s.",
219///     8000, "Africa");
220/// ```
221#[macro_export]
222macro_rules! warnf {
223  ($($args:expr),* $(,)?) => {{
224    use $crate::__private as __pw_log_crate;
225    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Warn, $($args),*)
226  }};
227}
228
229/// Deprecated alias for [`warnf!`].
230#[macro_export]
231macro_rules! pw_log_warnf {
232  ($($args:expr),* $(,)?) => {{
233    warnf!($($args),*)
234  }}
235}
236
237/// Emit an error level log message using `core::fmt` format string semantics.
238///
239/// ```
240/// use pw_log::error;
241///
242/// error!(
243///     "Log Fact: Before saws were invented, the {} was used prepare logs for use.",
244///     "adze" as &str);
245/// ```
246#[macro_export]
247macro_rules! error {
248  ($($args:expr),* $(,)?) => {{
249    use $crate::__private as __pw_log_crate;
250    __pw_log_crate::log!(__pw_log_crate::LogLevel::Error, $($args),*)
251  }};
252}
253
254/// Emit an error level log message using `printf` format string semantics.
255///
256/// ```
257/// use pw_log::errorf;
258///
259/// errorf!(
260///     "Log Fact: Before saws were invented, the %s was used prepare logs for use.",
261///     "adze");
262/// ```
263#[macro_export]
264macro_rules! errorf {
265  ($($args:expr),* $(,)?) => {{
266    use $crate::__private as __pw_log_crate;
267    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Error, $($args),*)
268  }};
269}
270
271/// Deprecated alias for [`errorf!`].
272#[macro_export]
273macro_rules! pw_log_errorf {
274  ($($args:expr),* $(,)?) => {{
275    errorf!($($args),*)
276  }}
277}
278
279/// Emit a critical level log message using `core::fmt` format string semantics.
280///
281/// ```
282/// use pw_log::critical;
283///
284/// critical!(
285///     "Log Fact: Until the {}th century, all ships' masts were made from a single log.",
286///     19 as u32);
287/// ```
288#[macro_export]
289macro_rules! critical {
290  ($($args:expr),* $(,)?) => {{
291    use $crate::__private as __pw_log_crate;
292    __pw_log_crate::log!(__pw_log_crate::LogLevel::Critical, $($args),*)
293  }};
294}
295
296/// Emit a critical level log message using `printf` format string semantics.
297///
298/// ```
299/// use pw_log::criticalf;
300///
301/// criticalf!(
302///     "Log Fact: Until the %dth century, all ships' masts were made from a single log.",
303///     19);
304/// ```
305#[macro_export]
306macro_rules! criticalf {
307  ($($args:expr),* $(,)?) => {{
308    use $crate::__private as __pw_log_crate;
309    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Critical, $($args),*)
310  }};
311}
312
313/// Deprecated alias for [`criticalf!`].
314#[macro_export]
315macro_rules! pw_log_criticalf {
316  ($($args:expr),* $(,)?) => {{
317    criticalf!($($args),*)
318  }}
319}
320
321/// Emit a fatal level log message using `core::fmt` format string semantics.
322///
323/// *Note*: `fatal` only emits a log message and does not cause a `panic!()`
324///
325/// ```
326/// use pw_log::fatal;
327///
328/// fatal!("Log Fact: All out of log facts! Timber!");
329/// ```
330#[macro_export]
331macro_rules! fatal {
332  ($($args:expr),* $(,)?) => {{
333    use $crate::__private as __pw_log_crate;
334    __pw_log_crate::log!(__pw_log_crate::LogLevel::Fatal, $($args),*)
335  }};
336}
337
338/// Emit a fatal level log message using `printf` format string semantics.
339///
340/// *Note*: `fatalf` only emits a log message and does not cause a `panic!()`
341///
342/// ```
343/// use pw_log::fatalf;
344///
345/// fatalf!("Log Fact: All out of log facts! Timber!");
346/// ```
347#[macro_export]
348macro_rules! fatalf {
349  ($($args:expr),* $(,)?) => {{
350    use $crate::__private as __pw_log_crate;
351    __pw_log_crate::logf!(__pw_log_crate::LogLevel::Fatal, $($args),*)
352  }};
353}
354
355/// Deprecated alias for [`fatalf!`].
356#[macro_export]
357macro_rules! pw_log_fatalf {
358  ($($args:expr),* $(,)?) => {{
359    fatalf!($($args),*)
360  }}
361}
362
363#[cfg(test)]
364mod tests {
365    // TODO(b/311262163): Add infrastructure for testing behavior of `pw_log` API.
366    // The syntax of that API is verified through doctests.
367}