1 | //! Log macro for log's kv-unstable backend.
|
2 | //!
|
3 | //! ## Example
|
4 | //!
|
5 | //! ```rust
|
6 | //! use kv_log_macro::info;
|
7 | //!
|
8 | //! femme::start(log::LevelFilter::Info).unwrap();
|
9 | //!
|
10 | //! info!("hello" );
|
11 | //! info!("hello" ,);
|
12 | //! info!("hello {}" , "cats" );
|
13 | //! info!("hello {}" , "cats" ,);
|
14 | //! info!("hello {}" , "cats" , {
|
15 | //! cat_1: "chashu" ,
|
16 | //! cat_2: "nori" ,
|
17 | //! });
|
18 | //! ```
|
19 |
|
20 | #![forbid (unsafe_code, future_incompatible, rust_2018_idioms)]
|
21 | #![deny (missing_debug_implementations, nonstandard_style)]
|
22 | #![warn (missing_docs, missing_doc_code_examples, unreachable_pub)]
|
23 | // #![cfg_attr(test, deny(warnings))]
|
24 |
|
25 | use log::{logger, LevelFilter, Record};
|
26 |
|
27 | use std::fmt;
|
28 |
|
29 | // publicly exporting so $crate::Level works.
|
30 | pub use log::Level;
|
31 |
|
32 | /// The statically resolved maximum log level.
|
33 | pub const STATIC_MAX_LEVEL: LevelFilter = log::STATIC_MAX_LEVEL;
|
34 |
|
35 | /// Returns the current maximum log level.
|
36 | #[inline ]
|
37 | pub fn max_level() -> LevelFilter {
|
38 | log::max_level()
|
39 | }
|
40 |
|
41 | /// The standard logging macro.
|
42 | ///
|
43 | /// ```
|
44 | /// use kv_log_macro::info;
|
45 | ///
|
46 | /// info!("hello" );
|
47 | /// info!("hello" ,);
|
48 | /// info!("hello {}" , "cats" );
|
49 | /// info!("hello {}" , "cats" ,);
|
50 | /// info!("hello {}" , "cats" , {
|
51 | /// cat_1: "chashu" ,
|
52 | /// cat_2: "nori" ,
|
53 | /// });
|
54 | /// ```
|
55 | #[macro_export (local_inner_macros)]
|
56 | macro_rules! log {
|
57 | // log!(target: "...", "...")
|
58 | (target: $target:expr, $lvl:expr, $e:expr) => {
|
59 | $crate::log_impl!(target: $target, $lvl, ($e));
|
60 | };
|
61 |
|
62 | // log!(target: "...", "...", args...)
|
63 | (target: $target:expr, $lvl:expr, $e:expr, $($rest:tt)*) => {
|
64 | $crate::log_impl!(target: $target, $lvl, ($e) $($rest)*);
|
65 | };
|
66 |
|
67 | // log!("...", args...)
|
68 | ($lvl:expr, $($arg:tt)+) => ($crate::log!(target: __log_module_path!(), $lvl, $($arg)+))
|
69 | }
|
70 |
|
71 | #[macro_export (local_inner_macros)]
|
72 | #[doc (hidden)]
|
73 | macro_rules! log_impl {
|
74 | // End of macro input
|
75 | (target: $target:expr, $lvl:expr, ($($arg:expr),*)) => {{
|
76 | let lvl = $lvl;
|
77 | if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
|
78 | $crate::__private_api_log(
|
79 | __log_format_args!($($arg),*),
|
80 | lvl,
|
81 | &($target, __log_module_path!(), __log_file!(), __log_line!()),
|
82 | None,
|
83 | );
|
84 | }
|
85 | }};
|
86 |
|
87 | // // Trailing k-v pairs containing no trailing comma
|
88 | (target: $target:expr, $lvl:expr, ($($arg:expr),*) { $($key:ident : $value:expr),* }) => {{
|
89 | if $lvl <= $crate::STATIC_MAX_LEVEL && $lvl <= $crate::max_level() {
|
90 | $crate::__private_api_log(
|
91 | __log_format_args!($($arg),*),
|
92 | $lvl,
|
93 | &(__log_module_path!(), __log_module_path!(), __log_file!(), __log_line!()),
|
94 | Some(&[$((__log_stringify!($key), &$value)),*])
|
95 | );
|
96 | }
|
97 | }};
|
98 |
|
99 | // Trailing k-v pairs with trailing comma
|
100 | (target: $target:expr, $lvl:expr, ($($e:expr),*) { $($key:ident : $value:expr,)* }) => {
|
101 | $crate::log_impl!(target: $target, $lvl, ($($e),*) { $($key : $value),* });
|
102 | };
|
103 |
|
104 | // Last expression arg with no trailing comma
|
105 | (target: $target:expr, $lvl:expr, ($($e:expr),*) $arg:expr) => {
|
106 | $crate::log_impl!(target: $target, $lvl, ($($e,)* $arg));
|
107 | };
|
108 |
|
109 | // Expression arg
|
110 | (target: $target:expr, $lvl:expr, ($($e:expr),*) $arg:expr, $($rest:tt)*) => {
|
111 | $crate::log_impl!(target: $target, $lvl, ($($e,)* $arg) $($rest)*);
|
112 | };
|
113 | }
|
114 |
|
115 | /// Logs a message at the trace level.
|
116 | #[macro_export (local_inner_macros)]
|
117 | macro_rules! trace {
|
118 | (target: $target:expr, $($arg:tt)+) => (
|
119 | log!(target: $target, $crate::Level::Trace, $($arg)+);
|
120 | );
|
121 | ($($arg:tt)+) => (
|
122 | log!($crate::Level::Trace, $($arg)+);
|
123 | )
|
124 | }
|
125 |
|
126 | /// Logs a message at the debug level.
|
127 | #[macro_export (local_inner_macros)]
|
128 | macro_rules! debug {
|
129 | (target: $target:expr, $($arg:tt)+) => (
|
130 | log!(target: $target, $crate::Level::Debug, $($arg)+);
|
131 | );
|
132 | ($($arg:tt)+) => (
|
133 | log!($crate::Level::Debug, $($arg)+);
|
134 | )
|
135 | }
|
136 |
|
137 | /// Logs a message at the info level.
|
138 | #[macro_export (local_inner_macros)]
|
139 | macro_rules! info {
|
140 | (target: $target:expr, $($arg:tt)+) => (
|
141 | log!(target: $target, $crate::Level::Info, $($arg)+);
|
142 | );
|
143 | ($($arg:tt)+) => (
|
144 | log!($crate::Level::Info, $($arg)+);
|
145 | )
|
146 | }
|
147 |
|
148 | /// Logs a message at the warn level.
|
149 | #[macro_export (local_inner_macros)]
|
150 | macro_rules! warn {
|
151 | (target: $target:expr, $($arg:tt)+) => (
|
152 | log!(target: $target, $crate::Level::Warn, $($arg)+);
|
153 | );
|
154 | ($($arg:tt)+) => (
|
155 | log!($crate::Level::Warn, $($arg)+);
|
156 | )
|
157 | }
|
158 |
|
159 | /// Logs a message at the error level.
|
160 | #[macro_export (local_inner_macros)]
|
161 | macro_rules! error {
|
162 | (target: $target:expr, $($arg:tt)+) => (
|
163 | log!(target: $target, $crate::Level::Error, $($arg)+);
|
164 | );
|
165 | ($($arg:tt)+) => (
|
166 | log!($crate::Level::Error, $($arg)+);
|
167 | )
|
168 | }
|
169 |
|
170 | /// Determines if a message logged at the specified level in that module will
|
171 | /// be logged.
|
172 | #[macro_export (local_inner_macros)]
|
173 | macro_rules! log_enabled {
|
174 | (target: $target:expr, $lvl:expr) => {{
|
175 | let lvl = $lvl;
|
176 | lvl <= $crate::STATIC_MAX_LEVEL
|
177 | && lvl <= $crate::max_level()
|
178 | && $crate::__private_api_enabled(lvl, $target)
|
179 | }};
|
180 | ($lvl:expr) => {
|
181 | log_enabled!(target: __log_module_path!(), $lvl)
|
182 | };
|
183 | }
|
184 |
|
185 | #[doc (hidden)]
|
186 | #[macro_export ]
|
187 | macro_rules! __log_format_args {
|
188 | ($($args:tt)*) => {
|
189 | format_args!($($args)*)
|
190 | };
|
191 | }
|
192 |
|
193 | #[doc (hidden)]
|
194 | #[macro_export ]
|
195 | macro_rules! __log_module_path {
|
196 | () => {
|
197 | module_path!()
|
198 | };
|
199 | }
|
200 |
|
201 | #[doc (hidden)]
|
202 | #[macro_export ]
|
203 | macro_rules! __log_file {
|
204 | () => {
|
205 | file!()
|
206 | };
|
207 | }
|
208 |
|
209 | #[doc (hidden)]
|
210 | #[macro_export ]
|
211 | macro_rules! __log_line {
|
212 | () => {
|
213 | line!()
|
214 | };
|
215 | }
|
216 |
|
217 | #[doc (hidden)]
|
218 | #[macro_export ]
|
219 | macro_rules! __log_stringify {
|
220 | ($($args:tt)*) => {
|
221 | stringify!($($args)*)
|
222 | };
|
223 | }
|
224 |
|
225 | // WARNING: this is not part of the crate's public API and is subject to change at any time
|
226 | #[doc (hidden)]
|
227 | pub fn __private_api_log(
|
228 | args: fmt::Arguments<'_>,
|
229 | level: Level,
|
230 | &(target: &str, module_path: &'static str, file: &'static str, line: u32): &(&str, &'static str, &'static str, u32),
|
231 | kvs: Option<&[(&str, &dyn log::kv::ToValue)]>,
|
232 | ) {
|
233 | logger().log(
|
234 | &Record&mut RecordBuilder<'_>::builder()
|
235 | .args(args)
|
236 | .level(level)
|
237 | .target(target)
|
238 | .module_path_static(Some(module_path))
|
239 | .file_static(file:Some(file))
|
240 | .line(Some(line))
|
241 | .key_values(&kvs)
|
242 | .build(),
|
243 | );
|
244 | }
|
245 | |