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 dependences 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; 55 pub use pw_log_backend::{pw_log_backend, pw_logf_backend}; 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] 70 macro_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] 94 macro_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] 108 macro_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] 123 macro_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] 139 macro_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] 148 macro_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] 164 macro_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] 181 macro_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] 190 macro_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] 206 macro_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] 223 macro_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] 232 macro_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] 248 macro_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] 265 macro_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] 274 macro_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] 290 macro_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, LogLevel}; 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] 307 macro_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] 316 macro_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] 332 macro_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, LogLevel}; 345 /// 346 /// fatalf!("Log Fact: All out of log facts! Timber!"); 347 /// ``` 348 #[macro_export] 349 macro_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] 358 macro_rules! pw_log_fatalf { 359 ($($args:expr),*) => {{ 360 fatalf!($($args),*) 361 }} 362 } 363 364 #[cfg(test)] 365 mod 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 } 369