Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect failure to install GUI log callback #1655

Merged
merged 3 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/re_log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub use log_once::{debug_once, error_once, info_once, trace_once, warn_once};

pub use {
channel_logger::*,
multi_logger::{add_boxed_logger, add_logger},
multi_logger::{add_boxed_logger, add_logger, MultiLoggerNotSetupError},
setup::*,
};

Expand Down
24 changes: 16 additions & 8 deletions crates/re_log/src/multi_logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,32 @@ static MULTI_LOGGER: MultiLogger = MultiLogger::new();

static HAS_MULTI_LOGGER: AtomicBool = AtomicBool::new(false);

/// Produced when trying to install additional loggers when [`init`] has not been called.
///
/// This can happen for example when users of the `rerun` crate use the `spawn` method,
/// and they aren't using `re_log`.
#[derive(Clone, Copy, Debug)]
pub struct MultiLoggerNotSetupError {}

/// Install the multi-logger as the default logger.
pub fn init() -> Result<(), log::SetLoggerError> {
HAS_MULTI_LOGGER.store(true, SeqCst);
log::set_logger(&MULTI_LOGGER)
}

/// Install an additional global logger.
pub fn add_boxed_logger(logger: Box<dyn log::Log>) {
add_logger(Box::leak(logger));
pub fn add_boxed_logger(logger: Box<dyn log::Log>) -> Result<(), MultiLoggerNotSetupError> {
add_logger(Box::leak(logger))
}

/// Install an additional global logger.
pub fn add_logger(logger: &'static dyn log::Log) {
debug_assert!(
HAS_MULTI_LOGGER.load(SeqCst),
"You forgot to setup multi-logging"
);
MULTI_LOGGER.loggers.write().push(logger);
pub fn add_logger(logger: &'static dyn log::Log) -> Result<(), MultiLoggerNotSetupError> {
if HAS_MULTI_LOGGER.load(SeqCst) {
MULTI_LOGGER.loggers.write().push(logger);
Ok(())
} else {
Err(MultiLoggerNotSetupError {})
}
}

/// Forward log messages to multiple [`log::log`] receivers.
Expand Down
5 changes: 3 additions & 2 deletions crates/re_log/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn setup_native_logging() {

let mut stderr_logger = env_logger::Builder::new();
stderr_logger.parse_filters(&log_filter);
crate::add_boxed_logger(Box::new(stderr_logger.build()));
crate::add_boxed_logger(Box::new(stderr_logger.build())).expect("Failed to install logger");
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -51,5 +51,6 @@ pub fn setup_web_logging() {
log::set_max_level(log::LevelFilter::Debug);
crate::add_boxed_logger(Box::new(crate::web_logger::WebLogger::new(
log::LevelFilter::Debug,
)));
)))
.expect("Failed to install logger");
}
2 changes: 1 addition & 1 deletion crates/re_ui/examples/re_ui_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub struct ExampleApp {
impl ExampleApp {
fn new(re_ui: re_ui::ReUi) -> Self {
let (logger, text_log_rx) = re_log::ChannelLogger::new(re_log::LevelFilter::Info);
re_log::add_boxed_logger(Box::new(logger));
re_log::add_boxed_logger(Box::new(logger)).unwrap();

let tree = egui_dock::Tree::new(vec![1, 2, 3]);

Expand Down
7 changes: 6 additions & 1 deletion crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ impl App {
shutdown: std::sync::Arc<std::sync::atomic::AtomicBool>,
) -> Self {
let (logger, text_log_rx) = re_log::ChannelLogger::new(re_log::LevelFilter::Info);
re_log::add_boxed_logger(Box::new(logger));
if re_log::add_boxed_logger(Box::new(logger)).is_err() {
// This can happen when `rerun` crate users call `spawn`. TODO(emilk): make `spawn` spawn a new process.
re_log::debug!(
"re_log not initialized - we won't see any log messages as GUI notifications"
);
}

let state: AppState = storage
.and_then(|storage| eframe::get_value(storage, eframe::APP_KEY))
Expand Down