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
//! Diagnostics from the places with nobody to return an error to.
//!
//! A file watcher on its own thread, a remote watch loop, a cache that could
//! not be written, a start that fell back to yesterday's configuration: each
//! reports and carries on. Where the report lands is layered, most specific
//! wins:
//!
//! 1. **The `tracing` feature**, when compiled in, takes everything: the
//! lines become events under the `dynamic_config` target and the layers
//! below never run. Filtering is the subscriber's business.
//! 2. **An installed sink** ([`set_log_sink`]) receives every line that
//! passes the level ([`set_log_level`]). This is the runtime path — it
//! is how the language bindings hand these lines to `logging` and to a
//! JavaScript callback, from a wheel that cannot flip a cargo feature.
//! 3. **The `log` feature**, when compiled in, forwards to the `log` crate's
//! global logger.
//! 4. **stderr**, prefixed `[dynamic-config]` — the default, unchanged since
//! 0.1: a library must not choose a logging framework for its users, and
//! silence would hide a watcher that is failing every reload.
use ;
use Arc;
use ArcSwapOption;
/// How loud the engine's own diagnostics are, for every path except a
/// compiled-in `tracing` subscriber (which does its own filtering).
///
/// Ordered: a level admits itself and everything louder, so
/// [`LogLevel::Info`] — the default, matching what the engine has always
/// printed — admits warnings too, and [`LogLevel::Off`] admits nothing.
static LEVEL: AtomicU8 = new;
/// Where a diagnostic line goes when the `tracing` feature is not compiled
/// in: the level it was emitted at, and the formatted line without the
/// `[dynamic-config]` prefix (the sink knows who it installed).
pub type LogSink = dyn Fn + Send + Sync;
static SINK: = const_empty;
/// Sets how loud the engine's diagnostics are. Process-wide, effective
/// immediately, cheap enough to call per test.
///
/// Under a compiled-in `tracing` subscriber this is a no-op: events are
/// always emitted and the subscriber filters.
/// Routes every diagnostic line that passes the level to `sink`, instead
/// of stderr or the `log` crate.
///
/// The contract, and it is load-bearing:
///
/// - **It is called on engine threads** — the watcher, a remote poll loop,
/// whatever thread called `reload()`. It must not block: a sink that
/// waits stalls reloads.
/// - **It must not call back into the engine.** Some lines are emitted
/// mid-transition; re-entrancy is not promised anywhere.
/// - One sink per process. Installing a second replaces the first;
/// [`clear_log_sink`] restores the default.
/// Removes an installed sink: lines fall back to the `log` crate when that
/// feature is compiled in, and to stderr otherwise.
/// The runtime dispatch, shared by both macros' non-`tracing` arms.
///
/// Wait-free on the hot path: one atomic load for the level and one
/// arc-swap load for the sink, and the line is not even formatted when the
/// level refuses it (the macros pass `format_args!` through).
///
/// Compiled out under `tracing`, whose macros never call it — the sink
/// and level still exist there as public API, inert by documented design.
pub
pub use ;