Let the daemon be heard

`fmt::init()` filtered almost everything out, so nobilis's own account of
what it was doing went nowhere - in a process whose output a frontend
already pipes somewhere useful. Which room it joined, why a connection
dropped, what a backend made of a frame it did not understand: all of it
switched off by default.

That is not a tidiness problem. Two protocol bugs in the Sneedchat backend
have now been reasoned about from first principles and got wrong, twice,
because the thing that would have answered them in a line was silent.

Info by default; RUST_LOG still wins where somebody sets it. Parsed here
rather than through tracing-subscriber's env-filter, which is not one of
its default features and is not worth a dependency change to read one
word - a per-target directive is read only for whether it asks for more.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-01 23:25:23 -04:00
co-authored by Claude Opus 5
parent 919a7c32b4
commit 1f339a8482
+36 -1
View File
@@ -138,9 +138,44 @@ fn acquire_singleton_lock(data_dir: &std::path::Path) -> Result<()> {
Ok(())
}
/// Logging, at a level somebody can actually see.
///
/// `fmt::init()` on its own filtered almost everything out, so the daemon's
/// own account of what it was doing - which room it joined, why a connection
/// dropped, what a backend made of a frame it did not understand - went
/// nowhere, in a process whose output a frontend already pipes somewhere
/// useful. Two protocol bugs were reasoned about from first principles and got
/// wrong because the thing that would have answered them was switched off.
///
/// So: info by default, and RUST_LOG still wins where somebody sets it.
/// Parsed here rather than through tracing-subscriber's env-filter, which is
/// not one of its default features and is not worth a dependency change to
/// read one word.
fn init_logging() {
let level = match std::env::var("RUST_LOG").unwrap_or_default().to_lowercase().as_str() {
"" | "info" => tracing::Level::INFO,
"trace" => tracing::Level::TRACE,
"debug" => tracing::Level::DEBUG,
"warn" => tracing::Level::WARN,
"error" => tracing::Level::ERROR,
// A per-target directive ("nobilis=debug"), which this does not parse.
// The most useful reading of "somebody asked for more" is more.
other => {
if other.contains("trace") {
tracing::Level::TRACE
} else if other.contains("debug") {
tracing::Level::DEBUG
} else {
tracing::Level::INFO
}
}
};
tracing_subscriber::fmt().with_max_level(level).init();
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
init_logging();
// Both the `irc` crate's tls-rust feature and the Discord backend's
// websocket/HTTP clients pull in rustls, but via different transitive