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.63+][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.2"
21//! ```
22//!
23//! This crate can be used in a few ways to record spans/events:
24//! - Using a [`RollingFileAppender`][rolling_struct] to perform writes to a log file. This will block on writes.
25//! - Using *any* type implementing [`std::io::Write`][write] in a non-blocking fashion.
26//! - Using a combination of [`NonBlocking`][non_blocking] and [`RollingFileAppender`][rolling_struct] 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`][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`][guard] 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`][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//! [write]: std::io::Write
107//! [guard]: non_blocking::WorkerGuard
108//! [make_writer]: tracing_subscriber::fmt::MakeWriter
109//! [rolling_struct]: rolling::RollingFileAppender
110//! [fmt_subscriber]: tracing_subscriber::fmt::Subscriber
111//!
112//! ## Non-Blocking Rolling File Appender
113//!
114//! ```rust
115//! # fn docs() {
116//! let file_appender = tracing_appender::rolling::hourly("/some/directory", "prefix.log");
117//! let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
118//! tracing_subscriber::fmt()
119//! .with_writer(non_blocking)
120//! .init();
121//! # }
122//! ```
123//!
124//! ## Supported Rust Versions
125//!
126//! `tracing-appender` is built against the latest stable release. The minimum supported
127//! version is 1.63. The current `tracing-appender` version is not guaranteed to build on
128//! Rust versions earlier than the minimum supported version.
129//!
130//! Tracing follows the same compiler support policies as the rest of the Tokio
131//! project. The current stable Rust compiler and the three most recent minor
132//! versions before it will always be supported. For example, if the current
133//! stable compiler version is 1.69, the minimum supported version will not be
134//! increased past 1.66, three minor versions prior. Increasing the minimum
135//! supported compiler version is not considered a semver breaking change as
136//! long as doing so complies with this policy.
137//!
138#![doc(
139 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
140 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
141)]
142#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
143#![warn(
144 missing_debug_implementations,
145 missing_docs,
146 rust_2018_idioms,
147 unreachable_pub,
148 bad_style,
149 dead_code,
150 improper_ctypes,
151 non_shorthand_field_patterns,
152 no_mangle_generic_items,
153 overflowing_literals,
154 path_statements,
155 patterns_in_fns_without_body,
156 private_in_public,
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][non_blocking]'s for more details.
179///
180/// [non_blocking]: mod@non_blocking
181///
182/// # Examples
183///
184/// ``` rust
185/// # fn docs() {
186/// let (non_blocking, _guard) = tracing_appender::non_blocking(std::io::stdout());
187/// let subscriber = tracing_subscriber::fmt().with_writer(non_blocking);
188/// tracing::subscriber::with_default(subscriber.finish(), || {
189/// tracing::event!(tracing::Level::INFO, "Hello");
190/// });
191/// # }
192/// ```
193pub fn non_blocking<T: Write + Send + 'static>(writer: T) -> (NonBlocking, WorkerGuard) {
194 NonBlocking::new(writer)
195}
196
197#[derive(Debug)]
198pub(crate) enum Msg {
199 Line(Vec<u8>),
200 Shutdown,
201}