ringlog/lib.rs
1// Copyright 2021 Twitter, Inc.
2// Licensed under the Apache License, Version 2.0
3// http://www.apache.org/licenses/LICENSE-2.0
4
5//! This crate provides an asynchronous logging backend that can direct logs to
6//! one or more outputs.
7//!
8//! The core of this crate is the `RingLog` type, which is constructed using a
9//! builder that is specific to your logging needs. After building the
10//! `RingLog`, it can be registered as the global logger using the `start`
11//! method. You will be left with a `Box<dyn Drain>` which should be
12//! periodically flushed outside of any critical path. For example, in an admin
13//! thread or dedicated logging thread.
14//!
15//! For logging to a single file, the `LogBuilder` type can be used to construct
16//! an `RingLog` which has low overhead, but directs log messages to a single
17//! `Output`.
18//!
19//! A `SamplingLogBuilder` can be used to construct an `RingLog` which will
20//! filter the log messages using sampling before directing the log messages to
21//! a single `Output`.
22//!
23//! A `MultiLogBuilder` can be used to construct an `RingLog` which routes log
24//! messages based on the `target` metadata of the log `Record`. If there is an
25//! `RingLog` registered for that specific `target`, then the log message will
26//! be routed to that instance of `RingLog`. Log messages that do not match any
27//! specific target will be routed to the default `RingLog` that has been added
28//! to the `MultiLogBuilder`. If there is no default, messages that do not match
29//! any specific target will be simply dropped.
30//!
31//! This combination of logging types allows us to compose a logging backend
32//! which meets the application's needs. For example, you can use a local log
33//! macro to set the target to some specific category and log those messages to
34//! a file, while letting all other log messages pass to standard out. This
35//! could allow splitting command/access/audit logs from the normal logging.
36
37pub use log::*;
38
39mod format;
40#[macro_use]
41mod macros;
42mod multi;
43mod nop;
44mod outputs;
45mod sampling;
46mod single;
47mod traits;
48
49pub use format::*;
50pub use multi::*;
51pub use nop::*;
52pub use outputs::*;
53pub use sampling::*;
54pub use single::*;
55pub use traits::*;
56
57#[cfg(feature = "metrics")]
58mod metrics;
59
60#[cfg(feature = "metrics")]
61use metrics::*;
62
63use clocksource::datetime::DateTime;
64use mpmc::Queue;
65
66pub(crate) type LogBuffer = Vec<u8>;
67
68/// A type which implements an asynchronous logging backend.
69pub struct RingLog {
70 pub(crate) logger: Box<dyn Log>,
71 pub(crate) drain: Box<dyn Drain>,
72 pub(crate) level_filter: LevelFilter,
73}
74
75impl RingLog {
76 /// Register the logger and return a type which implements `Drain`. It is
77 /// up to the user to periodically call flush on the resulting drain.
78 pub fn start(self) -> Box<dyn Drain> {
79 let level_filter = self.level_filter;
80 log::set_boxed_logger(self.logger)
81 .map(|()| log::set_max_level(level_filter))
82 .expect("failed to start logger");
83 self.drain
84 }
85}