logged_stream/lib.rs
1//! `logged-stream` provides a single wrapper type, [`LoggedStream`], that wraps any underlying IO
2//! object and logs every read, write, error, shutdown and drop that passes through it. The wrapper
3//! re-implements the same IO trait it wraps — [`Read`] / [`Write`], or the [`tokio`] asynchronous
4//! analogues [`AsyncRead`] / [`AsyncWrite`] — so it is a drop-in replacement for the stream it
5//! decorates and works transparently in both synchronous and asynchronous code.
6//!
7//! # Architecture
8//!
9//! [`LoggedStream`] is generic over four independent, pluggable parts. Each logged event flows
10//! through them in order: `event -> Formatter -> Filter -> Logger`.
11//!
12//! - **The inner IO object (`S`).** The stream you are wrapping. [`LoggedStream`] implements the
13//! same IO trait `S` does, so it slots in wherever `S` was used.
14//! - **Formatter ([`BufferFormatter`]).** Turns the read and written byte buffers into the display
15//! strings you see in the log.
16//! - **Filter ([`RecordFilter`]).** Decides which records are logged. It runs on every record kind,
17//! including shutdown and drop.
18//! - **Logger ([`Logger`]).** The sink that consumes accepted records.
19//!
20//! All three of [`BufferFormatter`], [`RecordFilter`] and [`Logger`] are public, `Send + 'static`
21//! and object-safe, with blanket implementations for `Box<...>` (and `Arc<T>` where `T: Sync` for
22//! [`BufferFormatter`]). You are free to supply your own implementation of any part.
23//!
24//! # Provided implementations
25//!
26//! ## Formatters ([`BufferFormatter`])
27//!
28//! Control how byte buffers are rendered. Each formatter stores a separator (default `:`) and
29//! exposes parallel constructors: `new`, `new_static`, `new_owned` and `new_default`.
30//!
31//! | Formatter | Renders each byte as |
32//! | --- | --- |
33//! | [`LowercaseHexadecimalFormatter`] | lowercase hexadecimal — `0a:ff` |
34//! | [`UppercaseHexadecimalFormatter`] | uppercase hexadecimal — `0A:FF` |
35//! | [`DecimalFormatter`] | decimal — `10:255` |
36//! | [`OctalFormatter`] | octal — `012:377` |
37//! | [`BinaryFormatter`] | binary — `00001010:11111111` |
38//!
39//! ## Filters ([`RecordFilter`])
40//!
41//! Decide which records reach the logger.
42//!
43//! | Filter | Behavior |
44//! | --- | --- |
45//! | [`DefaultFilter`] | Accepts every record. |
46//! | [`RecordKindFilter`] | Accepts only the record kinds in an allow-list given at construction. |
47//! | [`AllFilter`] | AND — a record passes only if every child filter accepts it (an empty list accepts everything). |
48//! | [`AnyFilter`] | OR — a record passes if any child filter accepts it (an empty list rejects everything). |
49//!
50//! ## Loggers ([`Logger`])
51//!
52//! Consume each accepted record.
53//!
54//! | Logger | Destination |
55//! | --- | --- |
56//! | [`ConsoleLogger`] | Emits records through the `log` facade. |
57//! | [`FileLogger`] | Writes records to a file. |
58//! | [`MemoryStorageLogger`] | Retains recent records in a bounded in-memory buffer. |
59//! | [`ChannelLogger`] | Sends records over an `mpsc` channel for handling elsewhere. |
60//!
61//! [`Write`]: std::io::Write
62//! [`Read`]: std::io::Read
63//! [`AsyncRead`]: tokio::io::AsyncRead
64//! [`AsyncWrite`]: tokio::io::AsyncWrite
65
66mod buffer_formatter;
67mod filter;
68mod logger;
69mod record;
70mod stream;
71
72pub use buffer_formatter::BinaryFormatter;
73pub use buffer_formatter::BufferFormatter;
74pub use buffer_formatter::DecimalFormatter;
75pub use buffer_formatter::LowercaseHexadecimalFormatter;
76pub use buffer_formatter::OctalFormatter;
77pub use buffer_formatter::UppercaseHexadecimalFormatter;
78pub use filter::AllFilter;
79pub use filter::AnyFilter;
80pub use filter::DefaultFilter;
81pub use filter::RecordFilter;
82pub use filter::RecordKindFilter;
83pub use logger::ChannelLogger;
84pub use logger::ConsoleLogger;
85pub use logger::FileLogger;
86pub use logger::Logger;
87pub use logger::MemoryStorageLogger;
88pub use record::Record;
89pub use record::RecordKind;
90pub use stream::LoggedStream;