base_console/lib.rs
1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4//! Automatic terminal and JSON output for ordinary `tracing` events.
5//!
6//! Applications call [`init`] once. Libraries continue using `tracing` directly.
7//! For existing subscribers and isolated captures, compose [`Console::layer`] instead.
8//!
9//! ```no_run
10//! base_console::init();
11//! tracing::info!(connections = 3_u64, "Server started");
12//! ```
13mod as_console_error;
14mod console;
15mod console_fields;
16mod console_format;
17mod console_init_error;
18mod failure;
19mod output_format;
20
21pub use console::Console;
22pub use console_init_error::ConsoleInitError;
23pub use failure::Failure;
24pub use output_format::OutputFormat;
25
26#[doc(hidden)]
27pub use tracing as __tracing;
28
29#[doc(hidden)]
30pub use as_console_error::AsConsoleError as __AsConsoleError;
31
32/// Emit a captured [`Failure`] as an error event at the caller's target and source location.
33///
34/// The error's causes remain typed; captured backtraces and original span context are included as text fields. Ordinary `tracing` subscribers can consume this event too. The failure expression is evaluated once. An explicit `target:` may override the caller's module path.
35///
36/// ```
37/// let failure = base_console::Failure::capture(std::io::Error::other("disconnected"));
38/// base_console::failure!(failure, "Request {} failed", 42);
39/// ```
40#[macro_export]
41macro_rules! failure {
42 (target: $target:expr, $failure:expr, $($message:tt)+) => {{
43 use $crate::__AsConsoleError as _;
44 let failure = &$failure;
45 $crate::__tracing::error!(
46 target: $target,
47 error = (*failure.error()).console_error(),
48 backtrace = failure.captured_backtrace().map($crate::__tracing::field::display),
49 span_trace = failure.span_trace(),
50 $($message)+
51 );
52 }};
53 ($failure:expr, $($message:tt)+) => {
54 $crate::failure!(target: module_path!(), $failure, $($message)+)
55 };
56}
57
58/// Install a global console using `RUST_LOG`, defaulting to `info`.
59///
60/// Output goes to stderr: terminal text with colour when attached to a terminal, otherwise newline-delimited JSON. The process's `log` logger is left unchanged. Libraries should leave installation to their application. Use [`try_init`] to handle setup errors.
61///
62/// # Panics
63///
64/// Panics if `RUST_LOG` cannot be read or parsed, or a global subscriber is already installed.
65#[track_caller]
66pub fn init() {
67 try_init().expect("could not initialize the console");
68}
69
70/// Try to install a global console using `RUST_LOG`, defaulting to `info`.
71///
72/// Uses the same output defaults as [`init`]. Returns an error if `RUST_LOG` cannot be read or parsed, or a global subscriber is already installed. The process's `log` logger is left unchanged.
73pub fn try_init() -> Result<(), ConsoleInitError> {
74 Console::default().with_env_filter()?.try_init()?;
75 Ok(())
76}