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