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}