🛈 Note: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem.

For the release documentation, please see docs.rs, instead.

tracing_appender/
lib.rs

1//! Writers for logging events and spans
2//!
3//! # Overview
4//!
5//! [`tracing`][tracing] is a framework for structured, event-based diagnostic information.
6//! `tracing-appender` allows events and spans to be recorded in a non-blocking manner through
7//! a dedicated logging thread. It also provides a [`RollingFileAppender`][file_appender] that can
8//! be used with _or_ without the non-blocking writer.
9//!
10//! *Compiler support: [requires `rustc` 1.51+][msrv]*
11//!
12//! [msrv]: #supported-rust-versions
13//! [file_appender]: rolling::RollingFileAppender
14//! [tracing]: https://docs.rs/tracing/
15//!
16//! # Usage
17//!
18//! Add the following to your `Cargo.toml`:
19//! ```toml
20//! tracing-appender = "0.1"
21//! ```
22//!
23//! This crate can be used in a few ways to record spans/events:
24//!  - Using a [`RollingFileAppender`] to perform writes to a log file. This will block on writes.
25//!  - Using *any* type implementing [`std::io::Write`] in a non-blocking fashion.
26//!  - Using a combination of [`NonBlocking`] and [`RollingFileAppender`] to allow writes to a log file
27//!    without blocking.
28//!
29//! ## File Appender
30//!
31//! The [`rolling` module][rolling] provides functions to create rolling and non-rolling file
32//! appenders.
33//!
34//! Rolling file appender rotation options are [`Rotation::MINUTELY`](rolling::Rotation::MINUTELY),
35//! [`Rotation::HOURLY`](rolling::Rotation::HOURLY), and
36//! [`Rotation::DAILY`](rolling::Rotation::DAILY).
37//!
38//! To create a non-rolling file appender, use
39//! [`tracing_appender::rolling::never(/*...*/)`](rolling::never) or
40//! [`Rotation::NEVER`](rolling::Rotation::NEVER).
41//!
42//! The following example creates an hourly rotating file appender that writes to
43//! `/some/directory/prefix.log.YYYY-MM-DD-HH`:
44//!
45//! ```rust
46//! # fn docs() {
47//! let file_appender = tracing_appender::rolling::hourly("/some/directory", "prefix.log");
48//! # }
49//! ```
50//!
51//! The file appender implements [`std::io::Write`]. To be used with
52//! [`tracing_subscriber::FmtSubscriber`][fmt_subscriber], it must be combined with a
53//! [`MakeWriter`][make_writer] implementation to be able to record tracing spans/event.
54//!
55//! See the [`rolling` module][rolling]'s documentation for more detail on how to use this file
56//! appender.
57//!
58//! ## Non-Blocking Writer
59//!
60//! The example below demonstrates the construction of a `non_blocking` writer with `std::io::stdout()`,
61//! which implements [`MakeWriter`][make_writer].
62//!
63//! ```rust
64//! # fn doc() {
65//! let (non_blocking, _guard) = tracing_appender::non_blocking(std::io::stdout());
66//! tracing_subscriber::fmt()
67//!     .with_writer(non_blocking)
68//!     .init();
69//! # }
70//! ```
71//! **Note:** `_guard` is a [`WorkerGuard`] which is returned by [`tracing_appender::non_blocking`][non_blocking]
72//! to ensure buffered logs are flushed to their output in the case of abrupt terminations of a process.
73//! See [`WorkerGuard` module][guard] for more details.
74//!
75//! The example below demonstrates the construction of a [`tracing_appender::non_blocking`][non_blocking]
76//! writer constructed with a [`std::io::Write`]:
77//!
78//! ```rust
79//! use std::io::Error;
80//!
81//! struct TestWriter;
82//!
83//! impl std::io::Write for TestWriter {
84//!     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
85//!         let buf_len = buf.len();
86//!         println!("{:?}", buf);
87//!         Ok(buf_len)
88//!     }
89//!
90//!     fn flush(&mut self) -> std::io::Result<()> {
91//!         Ok(())
92//!     }
93//! }
94//!
95//! # fn doc() {
96//! let (non_blocking, _guard) = tracing_appender::non_blocking(TestWriter);
97//! tracing_subscriber::fmt()
98//!     .with_writer(non_blocking)
99//!     .init();
100//! # }
101//! ```
102//!
103//! The [`non_blocking` module][non_blocking]'s documentation provides more detail on how to use `non_blocking`.
104//!
105//! [non_blocking]: mod@non_blocking
106//! [guard]: non_blocking::WorkerGuard
107//! [make_writer]: tracing_subscriber::fmt::MakeWriter
108//! [`RollingFileAppender`]: rolling::RollingFileAppender
109//! [fmt_subscriber]: tracing_subscriber::fmt::Subscriber
110//!
111//! ## Non-Blocking Rolling File Appender
112//!
113//! ```rust
114//! # fn docs() {
115//! let file_appender = tracing_appender::rolling::hourly("/some/directory", "prefix.log");
116//! let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
117//! tracing_subscriber::fmt()
118//!     .with_writer(non_blocking)
119//!     .init();
120//! # }
121//! ```
122//!
123//! ## Supported Rust Versions
124//!
125//! `tracing-appender` is built against the latest stable release. The minimum supported
126//! version is 1.51. The current `tracing-appender` version is not guaranteed to build on
127//! Rust versions earlier than the minimum supported version.
128//!
129//! Tracing follows the same compiler support policies as the rest of the Tokio
130//! project. The current stable Rust compiler and the three most recent minor
131//! versions before it will always be supported. For example, if the current
132//! stable compiler version is 1.69, the minimum supported version will not be
133//! increased past 1.66, three minor versions prior. Increasing the minimum
134//! supported compiler version is not considered a semver breaking change as
135//! long as doing so complies with this policy.
136//!
137#![doc(
138    html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
139    html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/favicon.ico",
140    issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
141)]
142#![warn(
143    missing_debug_implementations,
144    missing_docs,
145    rust_2018_idioms,
146    unreachable_pub,
147    bad_style,
148    dead_code,
149    improper_ctypes,
150    non_shorthand_field_patterns,
151    no_mangle_generic_items,
152    overflowing_literals,
153    path_statements,
154    patterns_in_fns_without_body,
155    private_interfaces,
156    private_bounds,
157    unconditional_recursion,
158    unused,
159    unused_allocation,
160    unused_comparisons,
161    unused_parens,
162    while_true
163)]
164use crate::non_blocking::{NonBlocking, WorkerGuard};
165
166use std::io::Write;
167
168pub mod non_blocking;
169
170pub mod rolling;
171
172mod worker;
173
174pub(crate) mod sync;
175
176/// Convenience function for creating a non-blocking, off-thread writer.
177///
178/// See the [`non_blocking` module's docs][mod@non_blocking]'s for more details.
179///
180/// # Examples
181///
182/// ``` rust
183/// # fn docs() {
184/// let (non_blocking, _guard) = tracing_appender::non_blocking(std::io::stdout());
185/// let subscriber = tracing_subscriber::fmt().with_writer(non_blocking);
186/// tracing::collect::with_default(subscriber.finish(), || {
187///    tracing::event!(tracing::Level::INFO, "Hello");
188/// });
189/// # }
190/// ```
191pub fn non_blocking<T: Write + Send + 'static>(writer: T) -> (NonBlocking, WorkerGuard) {
192    NonBlocking::new(writer)
193}
194
195#[derive(Debug)]
196pub(crate) enum Msg {
197    Line(Vec<u8>),
198    Shutdown,
199}