use bevy_app::{App, Plugin};
use bevy_log::{BoxedLayer, Level};
use tracing::{self, Subscriber};
use tracing_log::LogTracer;
use tracing_subscriber::{filter::FilterFn, fmt, layer::SubscriberExt, EnvFilter, Layer, Registry};
use crate::log_layer::GizmoLayer;
pub struct GizmoLogPlugin {
pub filter: String,
pub level: Level,
pub custom_layer: fn(app: &mut App) -> Option<BoxedLayer>,
}
impl Default for GizmoLogPlugin {
fn default() -> Self {
Self {
filter: "wgpu=error,naga=warn,[{gizmo}]=debug".to_owned(),
level: Level::INFO,
custom_layer: |_| None,
}
}
}
impl Plugin for GizmoLogPlugin {
fn build(&self, app: &mut bevy_app::App) {
let subscriber = Registry::default();
let to_stderr_layer = fmt::Layer::default().with_writer(std::io::stderr);
let to_stderr_layer = to_stderr_layer
.with_filter(FilterFn::new(|meta| meta.fields().field("gizmo").is_none()));
let subscriber = subscriber
.with((self.custom_layer)(app))
.with(GizmoLayer::new(app))
.with(self.global_filter_layer())
.with(to_stderr_layer);
Self::set_global_subscriber(subscriber);
}
}
impl GizmoLogPlugin {
fn global_filter_layer(&self) -> EnvFilter {
let default_filter = { format!("{},{}", self.level, self.filter) };
EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new(&default_filter))
.unwrap()
}
fn set_global_subscriber<S: Subscriber + Send + Sync + 'static>(subscriber: S) {
let logger_already_set = LogTracer::init().is_err();
let subscriber_already_set = tracing::subscriber::set_global_default(subscriber).is_err();
match (logger_already_set, subscriber_already_set) {
(true, true) => tracing::error!(
"Could not set global logger and tracing subscriber as they are already set."
),
(true, false) => tracing::error!("Could not set global logger as it is already set."),
(false, true) => {
tracing::error!("Could not set global tracing subscriber as it is already set.")
}
(false, false) => (),
}
}
}