Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/error/handler.rs
6849 views
1
use core::fmt::Display;
2
3
use crate::{component::Tick, error::BevyError, prelude::Resource};
4
use bevy_utils::prelude::DebugName;
5
use derive_more::derive::{Deref, DerefMut};
6
7
/// Context for a [`BevyError`] to aid in debugging.
8
#[derive(Debug, PartialEq, Eq, Clone)]
9
pub enum ErrorContext {
10
/// The error occurred in a system.
11
System {
12
/// The name of the system that failed.
13
name: DebugName,
14
/// The last tick that the system was run.
15
last_run: Tick,
16
},
17
/// The error occurred in a run condition.
18
RunCondition {
19
/// The name of the run condition that failed.
20
name: DebugName,
21
/// The last tick that the run condition was evaluated.
22
last_run: Tick,
23
/// The system this run condition is attached to.
24
system: DebugName,
25
/// `true` if this run condition was on a set.
26
on_set: bool,
27
},
28
/// The error occurred in a command.
29
Command {
30
/// The name of the command that failed.
31
name: DebugName,
32
},
33
/// The error occurred in an observer.
34
Observer {
35
/// The name of the observer that failed.
36
name: DebugName,
37
/// The last tick that the observer was run.
38
last_run: Tick,
39
},
40
}
41
42
impl Display for ErrorContext {
43
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44
match self {
45
Self::System { name, .. } => {
46
write!(f, "System `{name}` failed")
47
}
48
Self::Command { name } => write!(f, "Command `{name}` failed"),
49
Self::Observer { name, .. } => {
50
write!(f, "Observer `{name}` failed")
51
}
52
Self::RunCondition {
53
name,
54
system,
55
on_set,
56
..
57
} => {
58
write!(
59
f,
60
"Run condition `{name}` failed for{} system `{system}`",
61
if *on_set { " set containing" } else { "" }
62
)
63
}
64
}
65
}
66
}
67
68
impl ErrorContext {
69
/// The name of the ECS construct that failed.
70
pub fn name(&self) -> DebugName {
71
match self {
72
Self::System { name, .. }
73
| Self::Command { name, .. }
74
| Self::Observer { name, .. }
75
| Self::RunCondition { name, .. } => name.clone(),
76
}
77
}
78
79
/// A string representation of the kind of ECS construct that failed.
80
///
81
/// This is a simpler helper used for logging.
82
pub fn kind(&self) -> &str {
83
match self {
84
Self::System { .. } => "system",
85
Self::Command { .. } => "command",
86
Self::Observer { .. } => "observer",
87
Self::RunCondition { .. } => "run condition",
88
}
89
}
90
}
91
92
macro_rules! inner {
93
($call:path, $e:ident, $c:ident) => {
94
$call!(
95
"Encountered an error in {} `{}`: {}",
96
$c.kind(),
97
$c.name(),
98
$e
99
);
100
};
101
}
102
103
/// Defines how Bevy reacts to errors.
104
pub type ErrorHandler = fn(BevyError, ErrorContext);
105
106
/// Error handler to call when an error is not handled otherwise.
107
/// Defaults to [`panic()`].
108
///
109
/// When updated while a [`Schedule`] is running, it doesn't take effect for
110
/// that schedule until it's completed.
111
///
112
/// [`Schedule`]: crate::schedule::Schedule
113
#[derive(Resource, Deref, DerefMut, Copy, Clone)]
114
pub struct DefaultErrorHandler(pub ErrorHandler);
115
116
impl Default for DefaultErrorHandler {
117
fn default() -> Self {
118
Self(panic)
119
}
120
}
121
122
/// Error handler that panics with the system error.
123
#[track_caller]
124
#[inline]
125
pub fn panic(error: BevyError, ctx: ErrorContext) {
126
inner!(panic, error, ctx);
127
}
128
129
/// Error handler that logs the system error at the `error` level.
130
#[track_caller]
131
#[inline]
132
pub fn error(error: BevyError, ctx: ErrorContext) {
133
inner!(log::error, error, ctx);
134
}
135
136
/// Error handler that logs the system error at the `warn` level.
137
#[track_caller]
138
#[inline]
139
pub fn warn(error: BevyError, ctx: ErrorContext) {
140
inner!(log::warn, error, ctx);
141
}
142
143
/// Error handler that logs the system error at the `info` level.
144
#[track_caller]
145
#[inline]
146
pub fn info(error: BevyError, ctx: ErrorContext) {
147
inner!(log::info, error, ctx);
148
}
149
150
/// Error handler that logs the system error at the `debug` level.
151
#[track_caller]
152
#[inline]
153
pub fn debug(error: BevyError, ctx: ErrorContext) {
154
inner!(log::debug, error, ctx);
155
}
156
157
/// Error handler that logs the system error at the `trace` level.
158
#[track_caller]
159
#[inline]
160
pub fn trace(error: BevyError, ctx: ErrorContext) {
161
inner!(log::trace, error, ctx);
162
}
163
164
/// Error handler that ignores the system error.
165
#[track_caller]
166
#[inline]
167
pub fn ignore(_: BevyError, _: ErrorContext) {}
168
169