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 87 88 89 90 91 92 93 94 95 96
#![allow(clippy::needless_doctest_main)]
//! # A Bunyan formatter for [`tracing`]
//!
//! `tracing-bunyan-formatter` provides two [`Layer`]s implementation to be used on top of
//! a [`tracing`] [`Subscriber`]:
//! - [`JsonStorageLayer`], to attach contextual information to spans for ease of consumption by
//! downstream [`Layer`]s, via [`JsonStorage`] and [`Span`]'s [`extensions`](https://docs.rs/tracing-subscriber/0.2.5/tracing_subscriber/registry/struct.ExtensionsMut.html);
//! - [`BunyanFormattingLayer`]`, which emits a [bunyan](https://github.com/trentm/node-bunyan)-compatible formatted record upon entering a span,
//! existing a span and event creation.
//!
//! **Important**: each span will inherit all fields and properties attached to its parent - this is
//! currently not the behaviour provided by [`tracing_subscriber::fmt::Layer`](https://docs.rs/tracing-subscriber/0.2.5/tracing_subscriber/fmt/struct.Layer.html).
//!
//! ## Example
//!
//! ```rust
//! use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
//! use tracing::instrument;
//! use tracing::info;
//! use tracing_subscriber::Registry;
//! use tracing_subscriber::layer::SubscriberExt;
//!
//! #[instrument]
//! pub fn a_unit_of_work(first_parameter: u64) {
//! for i in 0..2 {
//! a_sub_unit_of_work(i);
//! }
//! info!(excited = "true", "Tracing is quite cool!");
//! }
//!
//! #[instrument]
//! pub fn a_sub_unit_of_work(sub_parameter: u64) {
//! info!("Events have the full context of their parent span!");
//! }
//!
//! fn main() {
//! let formatting_layer = BunyanFormattingLayer::new("tracing_demo".into(), std::io::stdout);
//! let subscriber = Registry::default()
//! .with(JsonStorageLayer)
//! .with(formatting_layer);
//! tracing::subscriber::set_global_default(subscriber).unwrap();
//!
//! info!("Orphan event without a parent span");
//! a_unit_of_work(2);
//! }
//! ```
//!
//! ## Console output
//!
//! <div>
//! <img src="https://raw.githubusercontent.com/LukeMathWalker/tracing-bunyan-formatter/master/images/ConsoleOutput.png" />
//! </div>
//! <hr/>
//!
//! If you pipe the output in the [`bunyan`](https://github.com/trentm/node-bunyan) CLI:
//! <div>
//! <img src="https://raw.githubusercontent.com/LukeMathWalker/tracing-bunyan-formatter/master/images/ConsoleBunyanOutput.png" />
//! </div>
//! <hr/>
//!
//!
//! ## Implementation strategy
//!
//! The layered approach we have pursued is not necessarily the most efficient,
//! but it makes it easier to separate different concerns and re-use common logic across multiple [`Layer`]s.
//!
//!
//!
//! While the current crate has no ambition to provide any sort of general purpose framework on top of
//! [`tracing-subscriber`]'s [`Layer`] trait, the information collected by [`JsonStorageLayer`] can be leveraged via
//! its public API by other downstream layers outside of this crate whose main concern is formatting.
//! It significantly lowers the amount of complexity you have to deal with if you are interested
//! in implementing your own formatter, for whatever reason or purpose.
//!
//! You can also add another enrichment layer following the [`JsonStorageLayer`] to collect
//! additional information about each span and store it in [`JsonStorage`].
//! We could have pursued this compositional approach to add `elapsed_milliseconds` to each span
//! instead of baking it in [`JsonStorage`] itself.
//!
//! ## Optional features
//!
//! You can enable the `arbitrary_precision` feature to handle numbers of arbitrary size losslessly. Be aware of a [known issue with untagged deserialization](https://github.com/LukeMathWalker/tracing-bunyan-formatter/issues/4).
//!
//! [`Layer`]: https://docs.rs/tracing-subscriber/0.2.5/tracing_subscriber/layer/trait.Layer.html
//! [`JsonStorageLayer`]: struct.JsonStorageLayer.html
//! [`JsonStorage`]: struct.JsonStorage.html
//! [`BunyanFormattingLayer`]: struct.BunyanFormattingLayer.html
//! [`Span`]: https://docs.rs/tracing/0.1.13/tracing/struct.Span.html
//! [`Subscriber`]: https://docs.rs/tracing-core/0.1.10/tracing_core/subscriber/trait.Subscriber.html
//! [`tracing`]: https://docs.rs/tracing
//! [`tracing`]: https://docs.rs/tracing-subscriber
mod formatting_layer;
mod storage_layer;
pub use formatting_layer::*;
pub use storage_layer::*;