-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Better warnings about invalid parameters #15500
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
Better warnings about invalid parameters #15500
Conversation
cd2fe8d
to
0bd22bb
Compare
I've noticed some problems with this approach, I'll be reworking it |
d217110
to
8e2c754
Compare
…15526) # Objective Fixes #15394 ## Solution Observers now validate params. System registry has a new error variant for when system running fails due to invalid parameters. Run once now returns a `Result<Out, RunOnceError>` instead of `Out`. This is more inline with system registry, which also returns a result. I'll address warning messages in #15500. ## Testing Added one test for each case. --- ## Migration Guide - `RunSystemOnce::run_system_once` and `RunSystemOnce::run_system_once_with` now return a `Result<Out>` instead of just `Out` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Zachary Harrold <zac@harrold.com.au>
c12cb04
to
5f1cdb5
Compare
Trying to construct a worst-case benchmark, where the systems do no work and there are no parameters to validate or extract: let mut world = World::new();
let mut schedule = Schedule::default();
for _ in 0..1000 {
schedule.add_systems(|| ());
}
for _ in 0..1000000 {
schedule.run(&mut world);
}
So there's about a standard deviation difference. But if these numbers were precise, the feature flag would allow removing 0.178ns per system. I don't think that's worth it. |
Thank you for your work, I'll remove the flag when im home :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the warning is now emitted from the param itself, which lets you include the param type in the message. And the warning state is stored on the system, which saves space and is easier to configure. As a consequence, if a system has multiple failing parameters, it only warns on the first one, right? That all seems reasonable, although the final result is a little surprising.
The policy update of a (function) system happens after param validation fails. While we can remove the short circuit, this won't patch a hole where missing parameters can change over time and we'll still only get warning about the first one (time-wise). I guess we could store the warning per system param?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, love the idea of giving more meaningful feedback to the user without spamming them needlessly. I have a note about a possible future PR, but definitely doesn't need to be in this PR.
/// No warning should ever be emitted. | ||
Never, | ||
/// The warning will be emitted once and status will update to [`Self::Never`]. | ||
Once, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Future PR: Seems reasonable to add an Always
policy as well:
/// State machine for emitting warnings when [system params are invalid](System::validate_param).
#[derive(Clone, Copy)]
pub enum ParamWarnPolicy {
/// No warning should ever be emitted.
Never,
/// The warning will be emitted once and status will update to [`Self::Never`].
Once,
/// The warning will be emitted each time the system is run.
Always,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had it but removed it as per previous feedback.
I think Always
will be a bit too annoying, but we could certainly use more complex policies:
- system just stopped running (prev frame valid, this frame invalid)
- invalid params changed
If we get some higher level logging with editor, we can do stuff like:
- system X stopped running at frame N because of invalid param P and is still not running till frame M
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I don't think we have a good way to test whether the right things get logged?
btw the PR description still mentions bevy_param_warn
Anyway, the implementation is looking good to me!
Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
# Objective System param validation warnings should be configurable and default to "warn once" (per system). Fixes: bevyengine#15391 ## Solution `SystemMeta` is given a new `ParamWarnPolicy` field. The policy decides whether warnings will be emitted by each system param when it fails validation. The policy is updated by the system after param validation fails. Example warning: ``` 2024-09-30T18:10:04.740749Z WARN bevy_ecs::system::function_system: System fallible_params::do_nothing_fail_validation will not run because it requested inaccessible system parameter Single<(), (With<Player>, With<Enemy>)> ``` Currently, only the first invalid parameter is displayed. Warnings can be disabled on function systems using `.param_never_warn()`. (there is also `.with_param_warn_policy(policy)`) ## Testing Ran `fallible_params` example. --------- Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
…evyengine#15526) # Objective Fixes bevyengine#15394 ## Solution Observers now validate params. System registry has a new error variant for when system running fails due to invalid parameters. Run once now returns a `Result<Out, RunOnceError>` instead of `Out`. This is more inline with system registry, which also returns a result. I'll address warning messages in bevyengine#15500. ## Testing Added one test for each case. --- ## Migration Guide - `RunSystemOnce::run_system_once` and `RunSystemOnce::run_system_once_with` now return a `Result<Out>` instead of just `Out` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Zachary Harrold <zac@harrold.com.au>
# Objective System param validation warnings should be configurable and default to "warn once" (per system). Fixes: bevyengine#15391 ## Solution `SystemMeta` is given a new `ParamWarnPolicy` field. The policy decides whether warnings will be emitted by each system param when it fails validation. The policy is updated by the system after param validation fails. Example warning: ``` 2024-09-30T18:10:04.740749Z WARN bevy_ecs::system::function_system: System fallible_params::do_nothing_fail_validation will not run because it requested inaccessible system parameter Single<(), (With<Player>, With<Enemy>)> ``` Currently, only the first invalid parameter is displayed. Warnings can be disabled on function systems using `.param_never_warn()`. (there is also `.with_param_warn_policy(policy)`) ## Testing Ran `fallible_params` example. --------- Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
…ia the GLOBAL_ERROR_HANDLER (#18454) # Objective There are two related problems here: 1. Users should be able to change the fallback behavior of *all* ECS-based errors in their application by setting the `GLOBAL_ERROR_HANDLER`. See #18351 for earlier work in this vein. 2. The existing solution (#15500) for customizing this behavior is high on boilerplate, not global and adds a great deal of complexity. The consensus is that the default behavior when a parameter fails validation should be set based on the kind of system parameter in question: `Single` / `Populated` should silently skip the system, but `Res` should panic. Setting this behavior at the system level is a bandaid that makes getting to that ideal behavior more painful, and can mask real failures (if a resource is missing but you've ignored a system to make the Single stop panicking you're going to have a bad day). ## Solution I've removed the existing `ParamWarnPolicy`-based configuration, and wired up the `GLOBAL_ERROR_HANDLER`/`default_error_handler` to the various schedule executors to properly plumb through errors . Additionally, I've done a small cleanup pass on the corresponding example. ## Testing I've run the `fallible_params` example, with both the default and a custom global error handler. The former panics (as expected), and the latter spams the error console with warnings 🥲 ## Questions for reviewers 1. Currently, failed system param validation will result in endless console spam. Do you want me to implement a solution for warn_once-style debouncing somehow? 2. Currently, the error reporting for failed system param validation is very limited: all we get is that a system param failed validation and the name of the system. Do you want me to implement improved error reporting by bubbling up errors in this PR? 3. There is broad consensus that the default behavior for failed system param validation should be set on a per-system param basis. Would you like me to implement that in this PR? My gut instinct is that we absolutely want to solve 2 and 3, but it will be much easier to do that work (and review it) if we split the PRs apart. ## Migration Guide `ParamWarnPolicy` and the `WithParamWarnPolicy` have been removed completely. Failures during system param validation are now handled via the `GLOBAL_ERROR_HANDLER`: please see the `bevy_ecs::error` module docs for more information. --------- Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
…ia the GLOBAL_ERROR_HANDLER (#18454) There are two related problems here: 1. Users should be able to change the fallback behavior of *all* ECS-based errors in their application by setting the `GLOBAL_ERROR_HANDLER`. See #18351 for earlier work in this vein. 2. The existing solution (#15500) for customizing this behavior is high on boilerplate, not global and adds a great deal of complexity. The consensus is that the default behavior when a parameter fails validation should be set based on the kind of system parameter in question: `Single` / `Populated` should silently skip the system, but `Res` should panic. Setting this behavior at the system level is a bandaid that makes getting to that ideal behavior more painful, and can mask real failures (if a resource is missing but you've ignored a system to make the Single stop panicking you're going to have a bad day). I've removed the existing `ParamWarnPolicy`-based configuration, and wired up the `GLOBAL_ERROR_HANDLER`/`default_error_handler` to the various schedule executors to properly plumb through errors . Additionally, I've done a small cleanup pass on the corresponding example. I've run the `fallible_params` example, with both the default and a custom global error handler. The former panics (as expected), and the latter spams the error console with warnings 🥲 1. Currently, failed system param validation will result in endless console spam. Do you want me to implement a solution for warn_once-style debouncing somehow? 2. Currently, the error reporting for failed system param validation is very limited: all we get is that a system param failed validation and the name of the system. Do you want me to implement improved error reporting by bubbling up errors in this PR? 3. There is broad consensus that the default behavior for failed system param validation should be set on a per-system param basis. Would you like me to implement that in this PR? My gut instinct is that we absolutely want to solve 2 and 3, but it will be much easier to do that work (and review it) if we split the PRs apart. `ParamWarnPolicy` and the `WithParamWarnPolicy` have been removed completely. Failures during system param validation are now handled via the `GLOBAL_ERROR_HANDLER`: please see the `bevy_ecs::error` module docs for more information. --------- Co-authored-by: MiniaczQ <xnetroidpl@gmail.com>
Objective
System param validation warnings should be configurable and default to "warn once" (per system).
Fixes: #15391
Solution
SystemMeta
is given a newParamWarnPolicy
field.The policy decides whether warnings will be emitted by each system param when it fails validation.
The policy is updated by the system after param validation fails.
Example warning:
Currently, only the first invalid parameter is displayed.
Warnings can be disabled on function systems using
.param_never_warn()
.(there is also
.with_param_warn_policy(policy)
)Testing
Ran
fallible_params
example.