bevy_ecs/error/
handler.rs1use core::fmt::Display;
2
3use crate::{change_detection::Tick, error::BevyError, prelude::Resource};
4use bevy_ecs::error::Severity;
5use bevy_utils::prelude::DebugName;
6use derive_more::derive::{Deref, DerefMut};
7
8#[derive(Debug, PartialEq, Eq, Clone)]
10pub enum ErrorContext {
11 System {
13 name: DebugName,
15 last_run: Tick,
17 },
18 RunCondition {
20 name: DebugName,
22 last_run: Tick,
24 system: DebugName,
26 on_set: bool,
28 },
29 Command {
31 name: DebugName,
33 },
34 Observer {
36 name: DebugName,
38 last_run: Tick,
40 },
41}
42
43impl Display for ErrorContext {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 match self {
46 Self::System { name, .. } => {
47 write!(f, "System `{name}` failed")
48 }
49 Self::Command { name } => write!(f, "Command `{name}` failed"),
50 Self::Observer { name, .. } => {
51 write!(f, "Observer `{name}` failed")
52 }
53 Self::RunCondition {
54 name,
55 system,
56 on_set,
57 ..
58 } => {
59 write!(
60 f,
61 "Run condition `{name}` failed for{} system `{system}`",
62 if *on_set { " set containing" } else { "" }
63 )
64 }
65 }
66 }
67}
68
69impl ErrorContext {
70 pub fn name(&self) -> DebugName {
72 match self {
73 Self::System { name, .. }
74 | Self::Command { name, .. }
75 | Self::Observer { name, .. }
76 | Self::RunCondition { name, .. } => name.clone(),
77 }
78 }
79
80 pub fn kind(&self) -> &str {
84 match self {
85 Self::System { .. } => "system",
86 Self::Command { .. } => "command",
87 Self::Observer { .. } => "observer",
88 Self::RunCondition { .. } => "run condition",
89 }
90 }
91}
92
93macro_rules! inner {
94 ($call:path, $e:ident, $c:ident) => {
95 $call!(
96 "Encountered an error in {} `{}`: {}",
97 $c.kind(),
98 $c.name(),
99 $e
100 );
101 };
102}
103
104pub type ErrorHandler = fn(BevyError, ErrorContext);
106
107#[derive(Resource, Deref, DerefMut, Copy, Clone)]
115pub struct FallbackErrorHandler(pub ErrorHandler);
116
117impl Default for FallbackErrorHandler {
118 fn default() -> Self {
119 Self(match_severity)
120 }
121}
122
123#[deprecated(since = "0.19.0", note = "Renamed to `FallbackErrorHandler`.")]
125pub type DefaultErrorHandler = FallbackErrorHandler;
126
127#[track_caller]
129#[inline]
130pub fn match_severity(err: BevyError, ctx: ErrorContext) {
131 match err.severity() {
132 Severity::Ignore => ignore(err, ctx),
133 Severity::Trace => trace(err, ctx),
134 Severity::Debug => debug(err, ctx),
135 Severity::Info => info(err, ctx),
136 Severity::Warning => warn(err, ctx),
137 Severity::Error => error(err, ctx),
138 Severity::Panic => panic(err, ctx),
139 }
140}
141
142#[track_caller]
144#[inline]
145pub fn panic(error: BevyError, ctx: ErrorContext) {
146 inner!(panic, error, ctx);
147}
148
149#[track_caller]
151#[inline]
152pub fn error(error: BevyError, ctx: ErrorContext) {
153 inner!(log::error, error, ctx);
154}
155
156#[track_caller]
158#[inline]
159pub fn warn(error: BevyError, ctx: ErrorContext) {
160 inner!(log::warn, error, ctx);
161}
162
163#[track_caller]
165#[inline]
166pub fn info(error: BevyError, ctx: ErrorContext) {
167 inner!(log::info, error, ctx);
168}
169
170#[track_caller]
172#[inline]
173pub fn debug(error: BevyError, ctx: ErrorContext) {
174 inner!(log::debug, error, ctx);
175}
176
177#[track_caller]
179#[inline]
180pub fn trace(error: BevyError, ctx: ErrorContext) {
181 inner!(log::trace, error, ctx);
182}
183
184#[track_caller]
186#[inline]
187pub fn ignore(_: BevyError, _: ErrorContext) {}