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}