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
//! Opt-in client-side tracing for the `decdn` CLI.
//!
//! The CLI is a terminal UI: by default it installs no tracing subscriber, so
//! its output is only the command's own stdout result and the stderr progress
//! bar. That keeps the common case clean, but it also means every
//! `tracing::debug!/info!/warn!` in `decdn-client`, `decdn-incentive`, and
//! `iroh` goes to a no-op collector — a stalled `decdn fetch` is silent on the
//! side that is actually failing.
//!
//! [`init`] turns logging on only when the operator asks for it, through
//! `-v`/`-vv`/`-vvv`, `--log-level`, or the `RUST_LOG` environment variable.
//! `RUST_LOG` wins (the same precedence the daemon uses), then `--log-level`,
//! then the `-v` count ([`requested_level`]). With none of them set the CLI
//! installs no subscriber and stays silent.
//!
//! # Progress-bar coexistence
//!
//! `decdn fetch` draws an [`indicatif`] progress bar to stderr, and a plain
//! stderr subscriber would shred it. When [`init`] installs a subscriber it
//! also creates one process-global [`indicatif::MultiProgress`]: log lines are
//! written through [`indicatif::MultiProgress::suspend`], and the fetch bar is
//! registered with the same `MultiProgress` (see [`attach_progress_bar`]), so
//! the two share stderr without corrupting each other. When no subscriber is
//! installed the bar draws straight to stderr as it always has.
use OnceLock;
use LogLevel;
/// The process-global [`indicatif::MultiProgress`] that log output and the
/// fetch progress bar share, set once by [`init`] when — and only when — a
/// subscriber is installed. Empty on the default (no-verbosity) path.
static PROGRESS: = new;
/// The level the command line asks for: an explicit `--log-level` wins over
/// the `-v` count, and a zero count with no `--log-level` asks for nothing.
pub const
/// Decide the tracing filter directive from `RUST_LOG` and the command-line
/// level (`--log-level` or `-v`, see [`requested_level`]), or `None` to stay
/// silent.
///
/// `RUST_LOG` (when present and not blank) takes precedence over the
/// command-line level, matching the daemon. With neither source set the CLI installs no subscriber
/// and its output is identical to a build without this module.
/// Level to use when the chosen directive is `RUST_LOG` but it fails to parse:
/// the operator's `--log-level` if they passed one, otherwise `info`. Mirrors
/// the daemon, so a broken `RUST_LOG` exported in the shell does not defeat an
/// explicit `--log-level` on the invocation.
/// Install the CLI tracing subscriber when the operator opts in.
///
/// Reads `RUST_LOG` and the parsed `--log-level`; if neither requests logging
/// this returns without touching global state, so the default terminal UX is
/// unchanged. Otherwise it installs a `fmt` subscriber whose writer routes
/// every line through a shared [`indicatif::MultiProgress`] so the `decdn
/// fetch` bar survives.
///
/// Call once, before command dispatch, so the subscriber covers every
/// subcommand.
/// Register a freshly built progress bar with the shared
/// [`indicatif::MultiProgress`] when a subscriber is installed, so log lines
/// and the bar coexist on stderr.
///
/// On the default path (no subscriber) the bar is returned untouched and draws
/// straight to stderr.
/// The [`indicatif::MultiProgress`] a multi-bar command (`bundle pull`) draws its
/// bars into: the process-global one when a subscriber is installed — so its bars
/// share stderr with log lines through [`indicatif::MultiProgress::suspend`] — or
/// a fresh standalone container on the default silent path, where there are no log
/// lines to coordinate with. Either way the bars stack coherently, and a
/// non-terminal stderr auto-hides them.
/// [`tracing_subscriber::fmt::MakeWriter`] that emits each log line through
/// [`indicatif::MultiProgress::suspend`], so writing never overlaps a redraw of
/// the fetch progress bar.
/// Per-event writer returned by [`SuspendingMakeWriter`]. Each `write` suspends
/// the shared [`indicatif::MultiProgress`] for the duration of the stderr write.