1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
//! Logging macros for **Stakker** //! //! There are five severity-based logging macros ([`trace!`], //! [`debug!`], [`info!`], [`warn!`] and [`error!`]) and one macro //! designed for logging records that have a fixed tag and no freeform //! text ([`audit!`]). Examples: //! //! ```ignore //! error!([cx], addr: %src_addr, port, "Failed to connect: {}", err); //! audit!([cx], TcpConnectFailure, addr: %src_addr, port); //! ``` //! //! The severity-based macros like [`error!`] all work the same way. //! The `[cx]` comes first, followed by an optional target //! specification (`target: "target-name"`), followed by optional //! key-value pairs, followed by a format-string and its arguments. //! //! For [`audit!`], `[cx]` comes first, followed by a tag for the //! record, followed by key-value pairs. The tag will normally be a //! plain identifier, but it could also be a literal string or an //! expression in parentheses which will be formatted to generate the //! tag. //! //! `[cx]` can refer to either an actor context (`stakker::Cx`) or a //! [`LogCx`]. Where the call is not being made from a context that //! provides a `LogID`, `[core]` may be passed instead of `[cx]`, //! which gives a `LogID` of zero. It's possible to log against a //! specific actor or other `LogID` source by using `[source, core]` //! instead of `[cx]`, which takes the `LogID` from that source using //! a `source.access_log_id()` call. (In general the `[a]` form must //! support `a.access_log_id()` and `a.access_core()`, and the `[a,b]` //! form must support `a.access_log_id()` and `b.access_core()`.) //! //! For key-value pairs, the most general form is `"key": expr`, but //! there are a number of shortcuts as follows: //! //! Shortcut | Equivalent //! --- | --- //! `size: file_size` | `"size": file_size` //! `size` | `"size": size` //! `packet.size` | `"size": packet.size` //! `tcp.packet.size` | `"size": tcp.packet.size` //! `%src_addr` | `"src_addr": format_args!("{}", src_addr)` //! `src_addr: %addr` | `"src_addr": format_args!("{}", addr)` //! `?stream` | `"stream": format_args!("{:?}", stream)` //! `stream: ?input_stream` | `"stream": format_args!("{:?}", input_stream)` //! //! Conversion of values is determined by implementation of the //! [`Visitable`] trait. All Rust primitives and standard collections //! are supported by [`Visitable`]. For your own types, there are two //! possibilities: either implement `Display` or `Debug` and use `%` //! or `?`, or else implement [`Visitable`] directly. The advantage //! of implementing [`Visitable`] is that in addition to mapping to a //! primitive instead of a string, you could also output a structured //! value such as an array or map to represent your type. //! //! [`LogCx`]: struct.LogCx.html //! [`Visitable`]: trait.Visitable.html //! [`audit!`]: macro.audit.html //! [`debug!`]: macro.debug.html //! [`error!`]: macro.error.html //! [`info!`]: macro.info.html //! [`trace!`]: macro.trace.html //! [`warn!`]: macro.warn.html mod kvdisp; mod logcx; mod macros; mod visit; pub use kvdisp::KvSingleLine; pub use logcx::LogCx; pub use visit::Visitable; // Re-export so that macros can access stakker::LogLevel #[doc(hidden)] pub use stakker; // TODO: Add loggers that log to 'log' crate, 'slog' crate, // 'tracing-core', etc // TODO: Maybe add adapter to dump KVs or maybe whole record to JSON // (single-line, packed) #[cfg(test)] mod test;