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

Add helper macro's for logging only once #10808

Merged
merged 10 commits into from
Dec 5, 2023
4 changes: 4 additions & 0 deletions crates/bevy_log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//! For more fine-tuned control over logging behavior, set up the [`LogPlugin`] or
//! `DefaultPlugins` during app initialization.

mod once;

#[cfg(feature = "trace")]
use std::panic;

Expand All @@ -28,6 +30,8 @@ pub mod prelude {
pub use bevy_utils::tracing::{
debug, debug_span, error, error_span, info, info_span, trace, trace_span, warn, warn_span,
};

pub use crate::{debug_once, error_once, info_once, trace_once, warn_once};
}

pub use bevy_utils::tracing::{
Expand Down
62 changes: 62 additions & 0 deletions crates/bevy_log/src/once.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/// Call some expression only once per call site.
#[macro_export]
macro_rules! once {
($expression:expr) => {{
use ::std::sync::atomic::{AtomicBool, Ordering};

static SHOULD_FIRE: AtomicBool = AtomicBool::new(true);
if SHOULD_FIRE.swap(false, Ordering::Relaxed) {
$expression;
}
}};
}

/// Call [`trace!`](crate::trace) once per call site.
///
/// Useful for logging within systems which are called every frame.
#[macro_export]
macro_rules! trace_once {
($($arg:tt)+) => ({
$crate::once!($crate::trace!($($arg)+))
});
}

/// Call [`debug!`](crate::debug) once per call site.
///
/// Useful for logging within systems which are called every frame.
#[macro_export]
macro_rules! debug_once {
($($arg:tt)+) => ({
$crate::once!($crate::debug!($($arg)+))
});
}

/// Call [`info!`](crate::info) once per call site.
///
/// Useful for logging within systems which are called every frame.
#[macro_export]
macro_rules! info_once {
($($arg:tt)+) => ({
$crate::once!($crate::info!($($arg)+))
});
}

/// Call [`warn!`](crate::warn) once per call site.
///
/// Useful for logging within systems which are called every frame.
#[macro_export]
macro_rules! warn_once {
($($arg:tt)+) => ({
$crate::once!($crate::warn!($($arg)+))
});
}

/// Call [`error!`](crate::error) once per call site.
///
/// Useful for logging within systems which are called every frame.
#[macro_export]
macro_rules! error_once {
($($arg:tt)+) => ({
$crate::once!($crate::error!($($arg)+))
});
}
28 changes: 28 additions & 0 deletions examples/app/logs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! This example illustrates how to use logs in bevy.

use bevy::log::once;
use bevy::prelude::*;

fn main() {
Expand All @@ -11,6 +12,7 @@ fn main() {
..default()
}))
.add_systems(Update, log_system)
.add_systems(Update, log_once_system)
.run();
}

Expand All @@ -30,3 +32,29 @@ fn log_system() {
// the format used here is super flexible. check out this documentation for more info:
// https://docs.rs/tracing-subscriber/*/tracing_subscriber/filter/struct.EnvFilter.html
}

fn log_once_system() {
// The 'once' variants of each log level are useful when a system is called every frame,
// but we still wish to inform the user only once. In other words, use these to prevent spam :)

trace_once!("one time noisy message");
debug_once!("one time debug message");
info_once!("some info which is printed only once");
warn_once!("some warning we wish to call out only once");
error_once!("some error we wish to report only once");

for i in 0..10 {
info_once!("logs once per call site, so this works just fine: {}", i);
}

// you can also use the 'once!' macro directly, in situations you want do do
// something expensive only once within the context of a continous system.
once!({
info!("doing expensive things");
let mut a: u64 = 0;
for i in 0..100000000 {
a += i;
}
info!("result of some expensive one time calculation: {}", a);
});
}