[Fixes #6224] Add logging variants of system piping (#6751)

# Objective

Fixes #6224, add ``dbg``, ``info``, ``warn`` and ``error`` system piping adapter variants to expand #5776, which call the corresponding re-exported [bevy_log macros](https://docs.rs/bevy/latest/bevy/log/macro.info.html) when the result is an error.

## Solution

* Added ``dbg``, ``info``, ``warn`` and ``error`` system piping adapter variants to ``system_piping.rs``. 
* Modified and added tests for these under examples in ``system_piping.rs``.
This commit is contained in:
Edvin Kjell 2022-12-11 18:10:03 +00:00
parent 81153a8b0c
commit aea4c5b1a4
3 changed files with 176 additions and 4 deletions

View File

@ -38,9 +38,10 @@ pub mod prelude {
Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage, Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage,
}, },
system::{ system::{
adapter as system_adapter, Commands, In, IntoPipeSystem, IntoSystem, Local, NonSend, adapter as system_adapter,
NonSendMut, ParallelCommands, ParamSet, Query, RemovedComponents, Res, ResMut, adapter::{dbg, error, ignore, info, unwrap, warn},
Resource, System, SystemParamFunction, Commands, In, IntoPipeSystem, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
ParamSet, Query, RemovedComponents, Res, ResMut, Resource, System, SystemParamFunction,
}, },
world::{FromWorld, Mut, World}, world::{FromWorld, Mut, World},
}; };

View File

@ -167,6 +167,7 @@ where
/// A collection of common adapters for [piping](super::PipeSystem) the result of a system. /// A collection of common adapters for [piping](super::PipeSystem) the result of a system.
pub mod adapter { pub mod adapter {
use crate::system::In; use crate::system::In;
use bevy_utils::tracing;
use std::fmt::Debug; use std::fmt::Debug;
/// Converts a regular function into a system adapter. /// Converts a regular function into a system adapter.
@ -232,6 +233,142 @@ pub mod adapter {
res.unwrap() res.unwrap()
} }
/// System adapter that utilizes the [`bevy_utils::tracing::info!`] macro to print system information.
///
/// # Examples
///
/// ```
/// use bevy_ecs::prelude::*;
/// #
/// # #[derive(StageLabel)]
/// # enum CoreStage { Update };
///
/// // Building a new schedule/app...
/// # use bevy_ecs::schedule::SystemStage;
/// # let mut sched = Schedule::default(); sched
/// # .add_stage(CoreStage::Update, SystemStage::parallel())
/// .add_system_to_stage(
/// CoreStage::Update,
/// // Prints system information.
/// data_pipe_system.pipe(system_adapter::info)
/// )
/// // ...
/// # ;
/// # let mut world = World::new();
/// # sched.run(&mut world);
///
/// // A system that returns a String output.
/// fn data_pipe_system() -> String {
/// "42".to_string()
/// }
/// ```
pub fn info<T: Debug>(In(data): In<T>) {
tracing::info!("{:?}", data);
}
/// System adapter that utilizes the [`bevy_utils::tracing::debug!`] macro to print the output of a system.
///
/// # Examples
///
/// ```
/// use bevy_ecs::prelude::*;
/// #
/// # #[derive(StageLabel)]
/// # enum CoreStage { Update };
///
/// // Building a new schedule/app...
/// # use bevy_ecs::schedule::SystemStage;
/// # let mut sched = Schedule::default(); sched
/// # .add_stage(CoreStage::Update, SystemStage::parallel())
/// .add_system_to_stage(
/// CoreStage::Update,
/// // Prints debug data from system.
/// parse_message_system.pipe(system_adapter::dbg)
/// )
/// // ...
/// # ;
/// # let mut world = World::new();
/// # sched.run(&mut world);
///
/// // A system that returns a Result<usize, String> output.
/// fn parse_message_system() -> Result<usize, std::num::ParseIntError> {
/// Ok("42".parse()?)
/// }
/// ```
pub fn dbg<T: Debug>(In(data): In<T>) {
tracing::debug!("{:?}", data);
}
/// System adapter that utilizes the [`bevy_utils::tracing::warn!`] macro to print the output of a system.
///
/// # Examples
///
/// ```
/// use bevy_ecs::prelude::*;
/// #
/// # #[derive(StageLabel)]
/// # enum CoreStage { Update };
///
/// // Building a new schedule/app...
/// # use bevy_ecs::schedule::SystemStage;
/// # let mut sched = Schedule::default(); sched
/// # .add_stage(CoreStage::Update, SystemStage::parallel())
/// .add_system_to_stage(
/// CoreStage::Update,
/// // Prints system warning if system returns an error.
/// warning_pipe_system.pipe(system_adapter::warn)
/// )
/// // ...
/// # ;
/// # let mut world = World::new();
/// # sched.run(&mut world);
///
/// // A system that returns a Result<(), String> output.
/// fn warning_pipe_system() -> Result<(), String> {
/// Err("Got to rusty?".to_string())
/// }
/// ```
pub fn warn<E: Debug>(In(res): In<Result<(), E>>) {
if let Err(warn) = res {
tracing::warn!("{:?}", warn);
}
}
/// System adapter that utilizes the [`bevy_utils::tracing::error!`] macro to print the output of a system.
///
/// # Examples
///
/// ```
/// use bevy_ecs::prelude::*;
/// #
/// # #[derive(StageLabel)]
/// # enum CoreStage { Update };
///
/// // Building a new schedule/app...
/// # use bevy_ecs::schedule::SystemStage;
/// # let mut sched = Schedule::default(); sched
/// # .add_stage(CoreStage::Update, SystemStage::parallel())
/// .add_system_to_stage(
/// CoreStage::Update,
/// // Prints system error if system fails.
/// parse_error_message_system.pipe(system_adapter::error)
/// )
/// // ...
/// # ;
/// # let mut world = World::new();
/// # sched.run(&mut world);
///
/// // A system that returns a Result<())> output.
/// fn parse_error_message_system() -> Result<(), String> {
/// Err("Some error".to_owned())
/// }
/// ```
pub fn error<E: Debug>(In(res): In<Result<(), E>>) {
if let Err(error) = res {
tracing::error!("{:?}", error);
}
}
/// System adapter that ignores the output of the previous system in a pipe. /// System adapter that ignores the output of the previous system in a pipe.
/// This is useful for fallible systems that should simply return early in case of an `Err`/`None`. /// This is useful for fallible systems that should simply return early in case of an `Err`/`None`.
/// ///

View File

@ -4,21 +4,43 @@
use anyhow::Result; use anyhow::Result;
use bevy::prelude::*; use bevy::prelude::*;
use bevy::log::LogPlugin;
use bevy::utils::tracing::Level;
fn main() { fn main() {
App::new() App::new()
.insert_resource(Message("42".to_string())) .insert_resource(Message("42".to_string()))
.insert_resource(OptionalWarning(Err("Got to rusty?".to_string())))
.add_plugin(LogPlugin {
level: Level::TRACE,
filter: "".to_string(),
})
.add_system(parse_message_system.pipe(handler_system)) .add_system(parse_message_system.pipe(handler_system))
.add_system(data_pipe_system.pipe(info))
.add_system(parse_message_system.pipe(dbg))
.add_system(warning_pipe_system.pipe(warn))
.add_system(parse_error_message_system.pipe(error))
.add_system(parse_message_system.pipe(ignore))
.run(); .run();
} }
#[derive(Resource, Deref)] #[derive(Resource, Deref)]
struct Message(String); struct Message(String);
// this system produces a Result<usize> output by trying to parse the Message resource #[derive(Resource, Deref)]
struct OptionalWarning(Result<(), String>);
// This system produces a Result<usize> output by trying to parse the Message resource.
fn parse_message_system(message: Res<Message>) -> Result<usize> { fn parse_message_system(message: Res<Message>) -> Result<usize> {
Ok(message.parse::<usize>()?) Ok(message.parse::<usize>()?)
} }
// This system produces a Result<()> output by trying to parse the Message resource.
fn parse_error_message_system(message: Res<Message>) -> Result<()> {
message.parse::<usize>()?;
Ok(())
}
// This system takes a Result<usize> input and either prints the parsed value or the error message // This system takes a Result<usize> input and either prints the parsed value or the error message
// Try changing the Message resource to something that isn't an integer. You should see the error // Try changing the Message resource to something that isn't an integer. You should see the error
// message printed. // message printed.
@ -28,3 +50,15 @@ fn handler_system(In(result): In<Result<usize>>) {
Err(err) => println!("encountered an error: {err:?}"), Err(err) => println!("encountered an error: {err:?}"),
} }
} }
// This system produces a String output by trying to clone the String from the Message resource.
fn data_pipe_system(message: Res<Message>) -> String {
message.0.clone()
}
// This system produces an Result<String> output by trying to extract a String from the
// OptionalWarning resource. Try changing the OptionalWarning resource to None. You should
// not see the warning message printed.
fn warning_pipe_system(message: Res<OptionalWarning>) -> Result<(), String> {
message.0.clone()
}