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 48 pub use pw_log_backend_api::LogLevel; 49 50 // Re-export dependencies of `pw_log` macros to be accessed via `$crate::__private`. 51 #[doc(hidden)] 52 pub 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] 69 macro_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] 93 macro_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] 107 macro_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] 122 macro_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] 138 macro_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] 147 macro_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] 163 macro_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] 180 macro_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] 189 macro_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] 205 macro_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] 222 macro_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] 231 macro_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] 247 macro_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] 264 macro_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] 273 macro_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] 289 macro_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] 306 macro_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] 315 macro_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] 331 macro_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] 348 macro_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] 357 macro_rules! pw_log_fatalf { 358 ($($args:expr),*) => {{ 359 fatalf!($($args),*) 360 }} 361 } 362 363 #[cfg(test)] 364 mod 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 } 368