feat(log): support customizing default log formatting (#17722)
The LogPlugin now allows overriding the default `tracing_subscriber::fmt::Layer` through a new `fmt_layer` option. This enables customization of the default log output format without having to replace the entire logging system. For example, to disable timestamps in the log output: ```rust fn fmt_layer(_app: &mut App) -> Option<bevy::log::BoxedFmtLayer> { Some(Box::new( bevy::log::tracing_subscriber::fmt::Layer::default() .without_time() .with_writer(std::io::stderr), )) } fn main() { App::new() .add_plugins(DefaultPlugins.set(bevy::log::LogPlugin { fmt_layer, ..default() })) .run(); } ``` This is different from the existing `custom_layer` option, because that option _adds_ additional layers to the subscriber, but can't modify the default formatter layer (at least, not to my knowledge). I almost always disable timestamps in my Bevy logs, and usually also tweak other default log formatting (such as `with_span_events`), which made it so that I always had to disable the default logger. This allows me to use everything the Bevy logger supports (including tracy support), while still formatting the default logs the way I like them. --------- Signed-off-by: Jean Mertz <git@jeanmertz.com>
This commit is contained in:
parent
bf42cb3532
commit
3b24f520b9
@ -56,6 +56,7 @@ use bevy_app::{App, Plugin};
|
|||||||
use tracing_log::LogTracer;
|
use tracing_log::LogTracer;
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
filter::{FromEnvError, ParseError},
|
filter::{FromEnvError, ParseError},
|
||||||
|
layer::Layered,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
registry::Registry,
|
registry::Registry,
|
||||||
EnvFilter, Layer,
|
EnvFilter, Layer,
|
||||||
@ -97,6 +98,7 @@ pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>);
|
|||||||
/// level: Level::DEBUG,
|
/// level: Level::DEBUG,
|
||||||
/// filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
|
/// filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
|
||||||
/// custom_layer: |_| None,
|
/// custom_layer: |_| None,
|
||||||
|
/// fmt_layer: |_| None,
|
||||||
/// }))
|
/// }))
|
||||||
/// .run();
|
/// .run();
|
||||||
/// }
|
/// }
|
||||||
@ -240,11 +242,38 @@ pub struct LogPlugin {
|
|||||||
///
|
///
|
||||||
/// Please see the `examples/log_layers.rs` for a complete example.
|
/// Please see the `examples/log_layers.rs` for a complete example.
|
||||||
pub custom_layer: fn(app: &mut App) -> Option<BoxedLayer>,
|
pub custom_layer: fn(app: &mut App) -> Option<BoxedLayer>,
|
||||||
|
|
||||||
|
/// Override the default [`tracing_subscriber::fmt::Layer`] with a custom one.
|
||||||
|
///
|
||||||
|
/// This differs from [`custom_layer`](Self::custom_layer) in that
|
||||||
|
/// [`fmt_layer`](Self::fmt_layer) allows you to overwrite the default formatter layer, while
|
||||||
|
/// `custom_layer` only allows you to add additional layers (which are unable to modify the
|
||||||
|
/// default formatter).
|
||||||
|
///
|
||||||
|
/// For example, you can use [`tracing_subscriber::fmt::Layer::without_time`] to remove the
|
||||||
|
/// timestamp from the log output.
|
||||||
|
///
|
||||||
|
/// Please see the `examples/log_layers.rs` for a complete example.
|
||||||
|
pub fmt_layer: fn(app: &mut App) -> Option<BoxedFmtLayer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A boxed [`Layer`] that can be used with [`LogPlugin`].
|
/// A boxed [`Layer`] that can be used with [`LogPlugin::custom_layer`].
|
||||||
pub type BoxedLayer = Box<dyn Layer<Registry> + Send + Sync + 'static>;
|
pub type BoxedLayer = Box<dyn Layer<Registry> + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
#[cfg(feature = "trace")]
|
||||||
|
type BaseSubscriber =
|
||||||
|
Layered<EnvFilter, Layered<Option<Box<dyn Layer<Registry> + Send + Sync>>, Registry>>;
|
||||||
|
|
||||||
|
#[cfg(feature = "trace")]
|
||||||
|
type PreFmtSubscriber = Layered<tracing_error::ErrorLayer<BaseSubscriber>, BaseSubscriber>;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "trace"))]
|
||||||
|
type PreFmtSubscriber =
|
||||||
|
Layered<EnvFilter, Layered<Option<Box<dyn Layer<Registry> + Send + Sync>>, Registry>>;
|
||||||
|
|
||||||
|
/// A boxed [`Layer`] that can be used with [`LogPlugin::fmt_layer`].
|
||||||
|
pub type BoxedFmtLayer = Box<dyn Layer<PreFmtSubscriber> + Send + Sync + 'static>;
|
||||||
|
|
||||||
/// The default [`LogPlugin`] [`EnvFilter`].
|
/// The default [`LogPlugin`] [`EnvFilter`].
|
||||||
pub const DEFAULT_FILTER: &str = "wgpu=error,naga=warn";
|
pub const DEFAULT_FILTER: &str = "wgpu=error,naga=warn";
|
||||||
|
|
||||||
@ -254,6 +283,7 @@ impl Default for LogPlugin {
|
|||||||
filter: DEFAULT_FILTER.to_string(),
|
filter: DEFAULT_FILTER.to_string(),
|
||||||
level: Level::INFO,
|
level: Level::INFO,
|
||||||
custom_layer: |_| None,
|
custom_layer: |_| None,
|
||||||
|
fmt_layer: |_| None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -328,10 +358,12 @@ impl Plugin for LogPlugin {
|
|||||||
#[cfg(feature = "tracing-tracy")]
|
#[cfg(feature = "tracing-tracy")]
|
||||||
let tracy_layer = tracing_tracy::TracyLayer::default();
|
let tracy_layer = tracing_tracy::TracyLayer::default();
|
||||||
|
|
||||||
// note: the implementation of `Default` reads from the env var NO_COLOR
|
let fmt_layer = (self.fmt_layer)(app).unwrap_or_else(|| {
|
||||||
// to decide whether to use ANSI color codes, which is common convention
|
// note: the implementation of `Default` reads from the env var NO_COLOR
|
||||||
// https://no-color.org/
|
// to decide whether to use ANSI color codes, which is common convention
|
||||||
let fmt_layer = tracing_subscriber::fmt::Layer::default().with_writer(std::io::stderr);
|
// https://no-color.org/
|
||||||
|
Box::new(tracing_subscriber::fmt::Layer::default().with_writer(std::io::stderr))
|
||||||
|
});
|
||||||
|
|
||||||
// bevy_render::renderer logs a `tracy.frame_mark` event every frame
|
// bevy_render::renderer logs a `tracy.frame_mark` event every frame
|
||||||
// at Level::INFO. Formatted logs should omit it.
|
// at Level::INFO. Formatted logs should omit it.
|
||||||
|
@ -4,7 +4,7 @@ use bevy::{
|
|||||||
log::{
|
log::{
|
||||||
tracing::{self, Subscriber},
|
tracing::{self, Subscriber},
|
||||||
tracing_subscriber::Layer,
|
tracing_subscriber::Layer,
|
||||||
BoxedLayer,
|
BoxedFmtLayer, BoxedLayer,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
@ -36,10 +36,24 @@ fn custom_layer(_app: &mut App) -> Option<BoxedLayer> {
|
|||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// While `custom_layer` allows you to add _additional_ layers, it won't allow you to override the
|
||||||
|
// default `tracing_subscriber::fmt::Layer` added by `LogPlugin`. To do that, you can use the
|
||||||
|
// `fmt_layer` option.
|
||||||
|
//
|
||||||
|
// In this example, we're disabling the timestamp in the log output.
|
||||||
|
fn fmt_layer(_app: &mut App) -> Option<BoxedFmtLayer> {
|
||||||
|
Some(Box::new(
|
||||||
|
bevy::log::tracing_subscriber::fmt::Layer::default()
|
||||||
|
.without_time()
|
||||||
|
.with_writer(std::io::stderr),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins.set(bevy::log::LogPlugin {
|
.add_plugins(DefaultPlugins.set(bevy::log::LogPlugin {
|
||||||
custom_layer,
|
custom_layer,
|
||||||
|
fmt_layer,
|
||||||
|
|
||||||
..default()
|
..default()
|
||||||
}))
|
}))
|
||||||
|
@ -30,6 +30,7 @@ fn main() {
|
|||||||
level: Level::TRACE,
|
level: Level::TRACE,
|
||||||
filter: "warn,log_layers_ecs=trace".to_string(),
|
filter: "warn,log_layers_ecs=trace".to_string(),
|
||||||
custom_layer,
|
custom_layer,
|
||||||
|
..default()
|
||||||
}))
|
}))
|
||||||
.add_systems(Startup, (log_system, setup))
|
.add_systems(Startup, (log_system, setup))
|
||||||
.add_systems(Update, print_logs)
|
.add_systems(Update, print_logs)
|
||||||
|
Loading…
Reference in New Issue
Block a user