pub struct LoggedStream<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static, L: Logger + 'static> { /* private fields */ }Expand description
Wrapper for an IO object that logs every read, write, error, shutdown and drop that passes through it.
LoggedStream wraps an underlying IO object implementing the Read / Write traits, or
their asynchronous tokio analogues AsyncRead / AsyncWrite, and logs all read and
write operations, errors, shutdowns and drops. It re-implements the same IO trait it wraps, so
it is a drop-in replacement that works transparently in both synchronous and asynchronous code.
§Architecture
LoggedStream is generic over four independent, pluggable parts. Each logged event flows
through them in order: event -> Formatter -> Filter -> Logger.
- The inner IO object (
S). The stream you are wrapping.LoggedStreamimplements the same IO traitSdoes, so it slots in whereverSwas used. - Formatter (
BufferFormatter). Turns the read and written byte buffers into the display strings you see in the log. - Filter (
RecordFilter). Decides which records are logged. It runs on every record kind, including shutdown and drop. - Logger (
Logger). The sink that consumes accepted records.
All three of BufferFormatter, RecordFilter and Logger are public, Send + 'static
and object-safe, with blanket implementations for Box<...> (and Arc<T> where T: Sync for
BufferFormatter). You are free to supply your own implementation of any part.
§Provided implementations
§Formatters (BufferFormatter)
Control how byte buffers are rendered. Each formatter stores a separator (default :) and
exposes parallel constructors: new, new_static, new_owned and new_default.
| Formatter | Renders each byte as |
|---|---|
LowercaseHexadecimalFormatter | lowercase hexadecimal — 0a:ff |
UppercaseHexadecimalFormatter | uppercase hexadecimal — 0A:FF |
DecimalFormatter | decimal — 10:255 |
OctalFormatter | octal — 012:377 |
BinaryFormatter | binary — 00001010:11111111 |
§Filters (RecordFilter)
Decide which records reach the logger.
| Filter | Behavior |
|---|---|
DefaultFilter | Accepts every record. |
RecordKindFilter | Accepts only the record kinds in an allow-list given at construction. |
AllFilter | AND — a record passes only if every child filter accepts it (an empty list accepts everything). |
AnyFilter | OR — a record passes if any child filter accepts it (an empty list rejects everything). |
§Loggers (Logger)
Consume each accepted record.
| Logger | Destination |
|---|---|
ConsoleLogger | Emits records through the log facade. |
FileLogger | Writes records to a file. |
MemoryStorageLogger | Retains recent records in a bounded in-memory buffer. |
ChannelLogger | Sends records over an mpsc channel for handling elsewhere. |
Implementations§
Source§impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static, L: Logger + 'static> LoggedStream<S, Formatter, Filter, L>
impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static, L: Logger + 'static> LoggedStream<S, Formatter, Filter, L>
Sourcepub fn new(stream: S, formatter: Formatter, filter: Filter, logger: L) -> Self
pub fn new(stream: S, formatter: Formatter, filter: Filter, logger: L) -> Self
Construct a new instance of LoggedStream using provided arguments.
Sourcepub fn log_open(&mut self, message: impl Into<String>)
pub fn log_open(&mut self, message: impl Into<String>)
Emit a custom RecordKind::Open record carrying message.
RecordKind::Open is never produced automatically by the read, write, shutdown and drop
machinery — this method is the way to emit one. Use it to annotate the start of a stream,
for example to record the peer of a freshly established connection
("Established connection with 127.0.0.1:8080") or other per-stream metadata.
Like every other record, the Open record is passed through the filter before it reaches
the logger, so a RecordKindFilter that does not allow Open will suppress it. The message
is logged verbatim; it is not run through the formatter, which only applies to byte buffers.
For asynchronous streams, call this before splitting the wrapper with tokio::io::split,
since the resulting halves do not expose it.
Source§impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static> LoggedStream<S, Formatter, Filter, MemoryStorageLogger>
impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static> LoggedStream<S, Formatter, Filter, MemoryStorageLogger>
pub fn get_log_records(&self) -> VecDeque<Record>
pub fn clear_log_records(&mut self)
Source§impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static> LoggedStream<S, Formatter, Filter, ChannelLogger>
impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static> LoggedStream<S, Formatter, Filter, ChannelLogger>
pub fn take_receiver(&mut self) -> Option<Receiver<Record>>
pub fn take_receiver_unchecked(&mut self) -> Receiver<Record>
Trait Implementations§
Source§impl<S: AsyncRead + Unpin + 'static, Formatter: BufferFormatter + Unpin + 'static, Filter: RecordFilter + Unpin + 'static, L: Logger + Unpin + 'static> AsyncRead for LoggedStream<S, Formatter, Filter, L>
impl<S: AsyncRead + Unpin + 'static, Formatter: BufferFormatter + Unpin + 'static, Filter: RecordFilter + Unpin + 'static, L: Logger + Unpin + 'static> AsyncRead for LoggedStream<S, Formatter, Filter, L>
Source§impl<S: AsyncWrite + Unpin + 'static, Formatter: BufferFormatter + Unpin + 'static, Filter: RecordFilter + Unpin + 'static, L: Logger + Unpin + 'static> AsyncWrite for LoggedStream<S, Formatter, Filter, L>
impl<S: AsyncWrite + Unpin + 'static, Formatter: BufferFormatter + Unpin + 'static, Filter: RecordFilter + Unpin + 'static, L: Logger + Unpin + 'static> AsyncWrite for LoggedStream<S, Formatter, Filter, L>
Source§fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, Error>>
fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize, Error>>
buf into the object. Read moreSource§fn poll_flush(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<(), Error>>
fn poll_flush( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), Error>>
Source§fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<(), Error>>
fn poll_shutdown( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), Error>>
Source§fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize, Error>>
fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize, Error>>
poll_write, except that it writes from a slice of buffers. Read moreSource§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
poll_write_vectored
implementation. Read moreSource§impl<S: Debug + 'static, Formatter: Debug + 'static, Filter: RecordFilter + Debug + 'static, L: Logger + Debug + 'static> Debug for LoggedStream<S, Formatter, Filter, L>
impl<S: Debug + 'static, Formatter: Debug + 'static, Filter: RecordFilter + Debug + 'static, L: Logger + Debug + 'static> Debug for LoggedStream<S, Formatter, Filter, L>
Source§impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Drop for LoggedStream<S, Formatter, Filter, L>
impl<S: 'static, Formatter: 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Drop for LoggedStream<S, Formatter, Filter, L>
Source§impl<S: Read + 'static, Formatter: BufferFormatter + 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Read for LoggedStream<S, Formatter, Filter, L>
impl<S: Read + 'static, Formatter: BufferFormatter + 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Read for LoggedStream<S, Formatter, Filter, L>
Source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
1.36.0 · Source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
read, except that it reads into a slice of buffers. Read moreSource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector)1.0.0 · Source§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
buf. Read more1.0.0 · Source§fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
buf. Read more1.6.0 · Source§fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
buf. Read moreSource§fn read_buf(&mut self, buf: BorrowedCursor<'_, u8>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_, u8>) -> Result<(), Error>
read_buf)Source§fn read_buf_exact(
&mut self,
cursor: BorrowedCursor<'_, u8>,
) -> Result<(), Error>
fn read_buf_exact( &mut self, cursor: BorrowedCursor<'_, u8>, ) -> Result<(), Error>
read_buf)cursor. Read more1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read. Read more1.0.0 · Source§fn chain<R>(self, next: R) -> Chain<Self, R>
fn chain<R>(self, next: R) -> Chain<Self, R>
1.0.0 · Source§fn take(self, limit: u64) -> Take<Self>where
Self: Sized,
fn take(self, limit: u64) -> Take<Self>where
Self: Sized,
limit bytes from it. Read moreSource§fn read_array<const N: usize>(&mut self) -> Result<[u8; N], Error>where
Self: Sized,
fn read_array<const N: usize>(&mut self) -> Result<[u8; N], Error>where
Self: Sized,
read_array)Source§impl<S: Write + 'static, Formatter: BufferFormatter + 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Write for LoggedStream<S, Formatter, Filter, L>
impl<S: Write + 'static, Formatter: BufferFormatter + 'static, Filter: RecordFilter + 'static, L: Logger + 'static> Write for LoggedStream<S, Formatter, Filter, L>
Source§fn write(&mut self, buf: &[u8]) -> Result<usize>
fn write(&mut self, buf: &[u8]) -> Result<usize>
Source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector)1.0.0 · Source§fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
Source§fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
write_all_vectored)Auto Trait Implementations§
impl<S, Formatter, Filter, L> Freeze for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> RefUnwindSafe for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> Send for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> Sync for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> Unpin for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> UnsafeUnpin for LoggedStream<S, Formatter, Filter, L>
impl<S, Formatter, Filter, L> UnwindSafe for LoggedStream<S, Formatter, Filter, L>
Blanket Implementations§
Source§impl<R> AsyncReadExt for R
impl<R> AsyncReadExt for R
Source§fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
Source§fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
Source§fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
buf. Read moreSource§fn read_u8(&mut self) -> ReadU8<&mut Self>where
Self: Unpin,
fn read_u8(&mut self) -> ReadU8<&mut Self>where
Self: Unpin,
Source§fn read_i8(&mut self) -> ReadI8<&mut Self>where
Self: Unpin,
fn read_i8(&mut self) -> ReadI8<&mut Self>where
Self: Unpin,
Source§fn read_u16(&mut self) -> ReadU16<&mut Self>where
Self: Unpin,
fn read_u16(&mut self) -> ReadU16<&mut Self>where
Self: Unpin,
Source§fn read_i16(&mut self) -> ReadI16<&mut Self>where
Self: Unpin,
fn read_i16(&mut self) -> ReadI16<&mut Self>where
Self: Unpin,
Source§fn read_u32(&mut self) -> ReadU32<&mut Self>where
Self: Unpin,
fn read_u32(&mut self) -> ReadU32<&mut Self>where
Self: Unpin,
Source§fn read_i32(&mut self) -> ReadI32<&mut Self>where
Self: Unpin,
fn read_i32(&mut self) -> ReadI32<&mut Self>where
Self: Unpin,
Source§fn read_u64(&mut self) -> ReadU64<&mut Self>where
Self: Unpin,
fn read_u64(&mut self) -> ReadU64<&mut Self>where
Self: Unpin,
Source§fn read_i64(&mut self) -> ReadI64<&mut Self>where
Self: Unpin,
fn read_i64(&mut self) -> ReadI64<&mut Self>where
Self: Unpin,
Source§fn read_u128(&mut self) -> ReadU128<&mut Self>where
Self: Unpin,
fn read_u128(&mut self) -> ReadU128<&mut Self>where
Self: Unpin,
Source§fn read_i128(&mut self) -> ReadI128<&mut Self>where
Self: Unpin,
fn read_i128(&mut self) -> ReadI128<&mut Self>where
Self: Unpin,
Source§fn read_f32(&mut self) -> ReadF32<&mut Self>where
Self: Unpin,
fn read_f32(&mut self) -> ReadF32<&mut Self>where
Self: Unpin,
Source§fn read_f64(&mut self) -> ReadF64<&mut Self>where
Self: Unpin,
fn read_f64(&mut self) -> ReadF64<&mut Self>where
Self: Unpin,
Source§fn read_u16_le(&mut self) -> ReadU16Le<&mut Self>where
Self: Unpin,
fn read_u16_le(&mut self) -> ReadU16Le<&mut Self>where
Self: Unpin,
Source§fn read_i16_le(&mut self) -> ReadI16Le<&mut Self>where
Self: Unpin,
fn read_i16_le(&mut self) -> ReadI16Le<&mut Self>where
Self: Unpin,
Source§fn read_u32_le(&mut self) -> ReadU32Le<&mut Self>where
Self: Unpin,
fn read_u32_le(&mut self) -> ReadU32Le<&mut Self>where
Self: Unpin,
Source§fn read_i32_le(&mut self) -> ReadI32Le<&mut Self>where
Self: Unpin,
fn read_i32_le(&mut self) -> ReadI32Le<&mut Self>where
Self: Unpin,
Source§fn read_u64_le(&mut self) -> ReadU64Le<&mut Self>where
Self: Unpin,
fn read_u64_le(&mut self) -> ReadU64Le<&mut Self>where
Self: Unpin,
Source§fn read_i64_le(&mut self) -> ReadI64Le<&mut Self>where
Self: Unpin,
fn read_i64_le(&mut self) -> ReadI64Le<&mut Self>where
Self: Unpin,
Source§fn read_u128_le(&mut self) -> ReadU128Le<&mut Self>where
Self: Unpin,
fn read_u128_le(&mut self) -> ReadU128Le<&mut Self>where
Self: Unpin,
Source§fn read_i128_le(&mut self) -> ReadI128Le<&mut Self>where
Self: Unpin,
fn read_i128_le(&mut self) -> ReadI128Le<&mut Self>where
Self: Unpin,
Source§fn read_f32_le(&mut self) -> ReadF32Le<&mut Self>where
Self: Unpin,
fn read_f32_le(&mut self) -> ReadF32Le<&mut Self>where
Self: Unpin,
Source§fn read_f64_le(&mut self) -> ReadF64Le<&mut Self>where
Self: Unpin,
fn read_f64_le(&mut self) -> ReadF64Le<&mut Self>where
Self: Unpin,
Source§fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
buf. Read more