Merge pull request #1651 from MatejKozlovsky/cli-warn-logging

CLI: log warnings to stderr by default
This commit is contained in:
BFlat
2026-10-30 00:09:39 +07:00
committed by GitHub
2 changed files with 34 additions and 6 deletions
+3
View File
@@ -279,6 +279,9 @@ fn utf8_args(raw: impl IntoIterator<Item = std::ffi::OsString>) -> Result<Vec<St
}
fn main() {
// Warnings and errors to standard error (`RUST_LOG` overrides), so a GPU that declines
// frames or runs out of memory says so instead of silently rendering on the CPU.
effectcraft_engine::logging::install_with("warn");
let raw = match utf8_args(std::env::args_os().skip(1)) {
Ok(raw) => raw,
Err(e) => fail_usage(&e),
+31 -6
View File
@@ -5,15 +5,15 @@
//! terminal, so that file is what a bug report can attach. The last few hundred warnings and
//! errors are also kept in memory for the System Compatibility Report.
//!
//! Levels: `info` for EffectCraft's own crates, `warn` for everything else (wgpu and naga are
//! chatty). `RUST_LOG` replaces that (a level such as `debug`, or per target:
//! Levels by default ([`DEFAULT_FILTER`]): `info` for EffectCraft's own crates, `warn` for
//! everything else (wgpu and naga are chatty). `RUST_LOG` replaces that (a level such as `debug`, or per target:
//! `effectcraft=debug,wgpu=warn`).
//!
//! Help ▸ Enable Logging ([`set_enabled`], the `help.enableLogging` command) additionally appends
//! every EffectCraft record to `Logs/EffectCraft Log.txt`, across launches.
//!
//! Frontends call [`install`] once at startup and the desktop app [`attach_session_log`] once the
//! settings folder is known; records logged before that are kept (up to [`MAX_PENDING`]) and
//! Frontends call [`install`] (or [`install_with`] for another default, as the CLI does with `warn`)
//! once at startup and the desktop app [`attach_session_log`] once the settings folder is known; records logged before that are kept (up to [`MAX_PENDING`]) and
//! written first. Writing never panics: a file that can't be created or written leaves standard
//! error as the only sink. Never log the control-channel token.
@@ -131,11 +131,21 @@ fn format_line(ts: &str, level: log::Level, thread: &str, target: &str, message:
/// Install the logger (once; later calls and other installed loggers are left alone).
pub fn install() {
install_with(DEFAULT_FILTER);
}
/// The directive string: `RUST_LOG` when it is set and nonblank, otherwise `default`.
fn filter_spec<'a>(rust_log: Option<&'a str>, default: &'a str) -> &'a str {
rust_log.filter(|s| !s.trim().is_empty()).unwrap_or(default)
}
/// [`install`] with `default` as the filter when `RUST_LOG` is unset or empty.
pub fn install_with(default: &str) {
static LOGGER: Logger = Logger;
if log::set_logger(&LOGGER).is_ok() {
let filter = FILTER.get_or_init(|| {
let spec = std::env::var("RUST_LOG").ok().filter(|s| !s.trim().is_empty());
parse_filter(spec.as_deref().unwrap_or(DEFAULT_FILTER))
let spec = std::env::var("RUST_LOG").ok();
parse_filter(filter_spec(spec.as_deref(), default))
});
log::set_max_level(filter.iter().map(|d| d.1).fold(LevelFilter::Info, Ord::max));
}
@@ -357,6 +367,21 @@ mod tests {
assert_eq!(level_for(&f, "naga"), LevelFilter::Warn);
}
/// The CLI's default (`warn`): warnings from every crate, no info chatter on stderr,
/// while a nonblank `RUST_LOG` overrides `default`.
#[test]
fn the_cli_filter_shows_only_warnings() {
assert_eq!(filter_spec(None, "warn"), "warn");
assert_eq!(filter_spec(Some(" "), "warn"), "warn");
assert_eq!(filter_spec(Some("info"), "warn"), "info");
let f = parse_filter(filter_spec(None, "warn"));
assert_eq!(level_for(&f, "effectcraft_gpu::context"), LevelFilter::Warn);
assert_eq!(level_for(&f, "effectcraft_engine::render_queue"), LevelFilter::Warn);
assert_eq!(level_for(&f, "wgpu_core::device"), LevelFilter::Warn);
let over = parse_filter(filter_spec(Some("info"), "warn"));
assert_eq!(level_for(&over, "effectcraft_gpu::context"), LevelFilter::Info);
}
#[test]
fn timestamps_are_utc_with_milliseconds() {
assert_eq!(timestamp(0), "1970-01-01T00:00:00.000Z");