1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//! Structured logging pipeline for Rust.
//!
//! `log-io` moves structured log records through three stages: a
//! [`Filter`] decides whether a record is wanted, a
//! [`Format`] serializes it (JSON, logfmt, or a
//! human-readable line), and one or more [`Sink`]s deliver the bytes.
//! The steady-state hot path performs no heap allocation, the data
//! model and formatters work under `no_std`, and the default build has
//! zero dependencies. Optional bridges plug the pipeline into the `log`
//! and `tracing` ecosystems.
//!
//! # Quick start
//!
//! use log_io::{Level, Logger};
//!
//! let logger = Logger::builder()
//! .level(Level::Info)
//! .env_filter("LOG_IO") // e.g. LOG_IO="info,my_app::db=debug"
//! .stdout_json()
//! .build();
//! let _guard = log_io::init(logger)?; // flushes on drop
//!
//! let port = 8080_u16;
//! log_io::info!("listening on port {port}", tls = true);
//! log_io::warn!(target: "my_app::db", "slow query", ms = 412_u64, table = "users");
//! # Ok::<(), log_io::SetGlobalError>(())
//! ```
//!
//! # Features
//!
//! | Feature | Default | Enables |
//! |---|---|---|
//! | `std` | yes | [`Logger`], sinks, [`context`], timestamps, the global logger |
//! | `json` | yes | [`format::JsonFormat`] |
//! | `logfmt` | yes | [`format::LogfmtFormat`] |
//! | `human` | yes | [`format::HumanFormat`] (works under `no_std`) |
//! | `log` | no | `compat::LogBridge`, a `log::Log` implementation (adds the `log` crate) |
//! | `tracing` | no | `compat::TracingLayer`, a `tracing-subscriber` layer (adds `tracing-core` and `tracing-subscriber`) |
//!
//! Without `std` the crate is `no_std` (no `alloc` needed): [`Record`],
//! [`Field`], [`Value`], [`Level`] and the three formatters, which write
//! to any [`core::fmt::Write`].
//!
//! # Threading and async
//!
//! [`Logger`] and every sink are `Send + Sync`. The built-in synchronous
//! sinks write on the calling thread under a mutex, so inside an async
//! runtime they block the executor thread for the duration of the
//! write; [`sink::NonBlocking`] moves the write to a background thread.
//! Context is thread-local; [`context::ContextSnapshot`] carries it into
//! tasks and other threads.
//!
//! # Durability
//!
//! Records at or above the flush level (default [`Level::Error`]) are
//! flushed to every sink before the logging call returns. The one
//! exception is a [`sink::NonBlocking`] sink with
//! [`Overflow::DropNewest`](sink::Overflow::DropNewest): it only queues
//! that flush so the call never waits, and a [`FlushGuard`] drop or
//! [`Logger::flush`] still drains it. Everything else may sit in a buffer until a flush, a [`FlushGuard`] drop, or the
//! last [`Logger`] clone being dropped. See [`sink::FileSink`] for the
//! exit paths that lose buffered data and how to avoid them.
//!
//! # Allocation
//!
//! Emitting a record through the built-in synchronous sinks does not
//! allocate in steady state, including timestamps, thread-local
//! context, default fields, and `format!`-style messages, as long as at
//! most 16 ambient (default + context) fields are attached. Creating a
//! context guard, capturing a context snapshot, and queueing a record on
//! [`sink::NonBlocking`] may allocate. `tests/alloc.rs` enforces this
//! with a counting allocator.
//!
//! # Stability
//!
//! Semantic versioning. `Value`, `Error`, `Metadata`, `Record` and the
//! configuration enums are `#[non_exhaustive]`, so they can grow in
//! minor releases. See `docs/MIGRATION.md` for upgrading from 1.x.
// The crate docs link to items behind every feature flag. Those links
// can only resolve when all features are enabled (as on docs.rs and in
// the CI docs job, which keep this lint at `deny`).
/// Crate version string, populated by Cargo at build time.
pub const VERSION: &str = env!;
pub use crate;
pub use crate;
pub use crateValue;
pub use crateFormat;
pub
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crateSink;
pub use crate__private;
// Compile and run every Rust code block in the README and the API
// reference as doctests, so the documentation cannot drift from the
// code. Needs every feature because the examples cover all of them.