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}