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
187
188
189
190
191
192
193
194
195
196
197
198
199
//! Process-wide backend lifecycle: [`start`], [`shutdown`], and their guards.
use Arc;
use OnceLock;
use ;
use cratebackend;
use crateLogLevel;
use crateLogger;
use crateSink;
/// Panic message produced by [`get_sink`] / [`create_sink`] (and the
/// macros, in later steps) when called before [`start`].
const NOT_STARTED_PANIC: &str = "insomnilog: call insomnilog::start() before using the logger";
/// Error returned by [`start`] when the backend has already been initialised
/// in this process.
///
/// `start` is conceptually one-shot per process: once called, subsequent calls
/// — including those after [`shutdown`] — return this error rather than
/// silently spawning a fresh backend with possibly different options.
;
/// RAII guard returned from [`start`]. Tears the backend down on drop.
///
/// Bind it for the lifetime you want logging to be alive — typically
/// `let _guard = insomnilog::start(opts)?;` near the top of `main`. The
/// `#[must_use]` attribute makes the compiler warn on `let _ = start(...)`,
/// which would drop the guard immediately.
/// Latch flipped by [`start`] to detect repeat initialisation.
///
/// Kept separate from [`BACKEND`] because `OnceLock::set` consumes its
/// argument: relying on the lock alone would force us to spawn a worker
/// thread before learning that initialisation is illegal. The latch keeps
/// the spawn out of the failing branch.
static STARTED: AtomicBool = new;
/// Process-wide backend, initialised exactly once by [`start`]. Subsequent
/// reads via [`shutdown`] go through `OnceLock::get`.
static BACKEND: = new;
/// Initialises the process-wide backend.
///
/// On success returns a [`ShutdownGuard`] whose `Drop` tears the backend
/// down (drain → join in later migration steps; just join for now). Bind
/// the guard in `main` for the desired lifetime of the logging system.
///
/// # Errors
///
/// Returns [`AlreadyStarted`] if `start` has already been called in this
/// process. There is no automatic restart.
///
/// # Panics
///
/// Panics if the backend worker thread cannot be spawned (the OS refused
/// to create a new thread).
/// Returns the process-wide backend.
///
/// # Panics
///
/// Panics if [`start`] has not been called in this process.
/// Drains and tears the backend down.
///
/// Idempotent: safe to call multiple times, before or after a
/// [`ShutdownGuard`] drops, and even if [`start`] has not been called (in
/// which case it is a no-op).
/// Returns the sink registered under `name`, if any.
///
/// # Panics
///
/// Panics if [`start`] has not been called in this process.
/// Registers `sink` under `name`.
///
/// The error carries the existing `Arc` so the caller can inspect or compare
/// it.
///
/// # Errors
///
/// Returns <code>Err([`backend::SinkAlreadyRegistered`])</code> if a sink is
/// already registered under `name`.
///
/// # Panics
///
/// Panics if [`start`] has not been called in this process.
/// Returns the logger registered under `name`, if any.
///
/// # Panics
///
/// Panics if [`start`] has not been called in this process.
/// Creates a new logger under `name` with the given `sinks` and `level`.
///
/// **`level` gates emission for every sink.** The producer-side check against
/// `level` runs on the macro hot path before any sink sees the record,
/// so a sink configured *more permissive* than this logger never receives the
/// difference. The effective level for any sink is
/// `max(logger.level, sink.level)`. To get more output, lower this `level`,
/// not the sink's.
///
/// # Errors
///
/// Returns <code>Err([crate::LoggerAlreadyRegistered])</code> if a logger is already
/// registered under `name`. The error carries the existing `Arc<Logger>`.
///
/// # Panics
///
/// Panics if [`start`] has not been called in this process.
/// Eagerly registers the calling thread with the backend, paying the queue
/// allocation and context push upfront rather than on the first log call.
///
/// Idempotent: a second call from the same thread is a no-op because the
/// thread-local producer slot is already populated. A subsequent log macro call
/// on the same thread also reuses the slot and does not register a second context.
///
/// # Panics
///
/// - Panics if [`start`] has not been called.
/// - Panics if called from the backend worker thread (would create infinite
/// dispatch loop).