-
Notifications
You must be signed in to change notification settings - Fork 615
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
refactor(error): clean-up direct error formatting (part 1) #13763
Conversation
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
1d92df9
to
b3603f9
Compare
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
4dd80b0
to
30b8172
Compare
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
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.
Some guides for refactoring
.map_err(|e| ExprError::Internal(anyhow!("failed to encode row, error: {}", e)))?; | ||
.context("failed to encode row")?; |
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.
Use Anyhow::Context::context
to create a new internal error with the given message, while keeping the error source.
@@ -101,8 +101,11 @@ where | |||
RwConfig::default() | |||
} else { | |||
let config_str = fs::read_to_string(path) | |||
.unwrap_or_else(|e| panic!("failed to open config file '{}': {}", path, e)); | |||
toml::from_str(config_str.as_str()).unwrap_or_else(|e| panic!("parse error {}", e)) | |||
.with_context(|| format!("failed to open config file at `{path}`")) |
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.
Use with_context
if evaluating the message is not const
.
@@ -231,8 +231,8 @@ impl BoxedExecutorBuilder for InsertExecutor { | |||
.map(|IndexAndExpr { index: i, expr: e }| { | |||
Ok(( | |||
i as usize, | |||
build_from_prost(&e.ok_or_else(|| anyhow!("expression is None"))?) | |||
.map_err(|e| anyhow!("failed to build expression: {}", e))?, | |||
build_from_prost(&e.context("expression is None")?) |
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.
Besides Result
, context
is also applicable to Option
s.
If you only have the error, use anyhow::anyhow!(source).context("context message")
.
let mut output = task.get_task_output(&pb_task_output_id).map_err(|e| { | ||
let mut output = task.get_task_output(&pb_task_output_id).inspect_err(|e| { | ||
error!( | ||
"failed to get task output of Task {:?} in local execution mode", | ||
task_id | ||
error = %e.as_report(), | ||
?task_id, | ||
"failed to get task output in local execution mode", | ||
); | ||
e | ||
})?; |
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.
Prefer inspect_err
if not going to change the error variant. For example, logging it out.
error!( | ||
"failed to build executors and trigger execution of Task {:?}: {}", | ||
task_id, e | ||
error = %e.as_report(), | ||
?task_id, | ||
"failed to build executors and trigger execution" | ||
); |
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.
To print an error with tracing
, specify a field with error = %e.as_report()
. Explanations:
- Use the
Report
wrapper for error to visit the source chain when visiting. - Telling
tracing
to useDisplay
format with%
. - Normalize the error field name to
error
witherror = <expr>
@@ -671,7 +672,7 @@ impl<C: BatchTaskContext> BatchTaskExecution<C> { | |||
|
|||
let error = error.map(Arc::new); | |||
*self.failure.lock() = error.clone(); | |||
let err_str = error.as_ref().map(|e| e.to_string()); | |||
let err_str = error.as_ref().map(|e| e.to_report_string()); |
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.
If we really want to eagerly format the error, use to_report_string
to replace to_string
. This is basically an alias of e.as_report().to_string()
.
Note that to_string
implies Display
trait. The behavior of {}
{:#}
{:?}
{:#?}
differ, and there're also corresponding to_report_string
variants. Check the documentation of Report
.
.map_err(|e| tonic::Status::internal(format!("{}", e)))?; | ||
.map_err(|e| e.to_status(Code::Internal, "compute"))?; | ||
let stream_config = serde_json::to_string(&self.stream_mgr.config().await) | ||
.map_err(|e| tonic::Status::internal(format!("{}", e)))?; | ||
.map_err(|e| e.to_status(Code::Internal, "compute"))?; |
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.
Use to_status
to convert an error to tonic::Status
. If this is not ad-hoc, you may want to directly impl From<..> for tonic::Status
.
src/error/src/tonic.rs
Outdated
@@ -145,6 +146,7 @@ impl std::fmt::Display for TonicStatusWrapper { | |||
write!(f, " to {} service", service_name)?; | |||
} | |||
write!(f, " failed: {}: ", self.0.code())?; | |||
#[allow(rw::format_error)] // intentionally format the source itself |
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.
Ignore the customized lints just like how we do for clippy
.
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.
#[allow(rw::format_error)] // intentionally format the source itself | |
#[expect(rw::format_error)] // intentionally format the source itself |
if let Err(_err) = shutdown_sender.send(()) { | ||
tracing::warn!("Failed to send shutdown"); |
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.
No need to print the SendError
if the value is meaningless, as it does not contain useful information.
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.
Note: the value is the data not sent
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
#[derive(thiserror::Error, Debug, thiserror_ext::Box)] | ||
#[derive( | ||
thiserror::Error, | ||
Debug, | ||
thiserror_ext::Arc, | ||
thiserror_ext::ContextInto, | ||
thiserror_ext::Construct, | ||
)] |
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.
Why Arc
What is ContextInto
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.
Why
Arc
The error is cloned here:
risingwave/src/stream/src/task/barrier_manager/managed_state.rs
Lines 179 to 181 in f5efe3f
&& collect_notifier | |
.send(Err(err.clone())) | |
.is_err() |
What is
ContextInto
It's another kind of constructor derivation! 😄 Basically, we can write
risingwave/src/stream/src/task/barrier_manager/managed_state.rs
Lines 167 to 168 in f5efe3f
// Attach the actor id to the error. | |
let err = err.into_unexpected_exit(actor_id); |
as a sugar of
let err = StreamError::unexpected_exit(err, actor_id);
It's not that sweet here, but can be useful for transforming the Result
s as it's also implemented on Result
s.
risingwave/src/common/heap_profiling/src/jeprof.rs
Lines 49 to 52 in f5efe3f
output.status.exit_ok().into_exit_error( | |
String::from_utf8_lossy(&output.stdout), | |
String::from_utf8_lossy(&output.stderr), | |
)?; |
It's highly inspired by anyhow::Context
and snafu::Context
. I'll write the rustdoc for it ASAP.
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.
Oh, the context here is always evaluated. 😕 Perhaps I need to introduce a with
method.
risingwave/src/common/heap_profiling/src/jeprof.rs
Lines 49 to 52 in f5efe3f
output.status.exit_ok().into_exit_error( | |
String::from_utf8_lossy(&output.stdout), | |
String::from_utf8_lossy(&output.stderr), | |
)?; |
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.
Others LGTM. 🫡 for the work. But I'd be even happier if the PR can be even smaller.
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
.cargo/config.toml
Outdated
# uncomment the following two lines to enable `TaskLocalAlloc` | ||
|
||
# Register the `rw` tool for referencing the custom lints in attributes like `#[allow(rw::xx)]`. | ||
# This is essentially the same as `#![..]` in each crate root. |
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.
Oh, can we use this to enable all rust features? 🫣
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.
Yeah, really interesting! But it seems painful to also override RUSTDOCFLAGS
. 😕
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.
Seems not to work for doc tests. I'll manually register it. 🤡
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #13763 +/- ##
==========================================
+ Coverage 68.19% 68.26% +0.06%
==========================================
Files 1524 1524
Lines 262232 262275 +43
==========================================
+ Hits 178829 179033 +204
+ Misses 83403 83242 -161
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.
What's changed and what's your intention?
See backgrounds in #11443. TL;DR: formatting errors with
{}
or.to_string
can cause the loss of the error source. Usethiserror_ext::Report
instead.Empowered by the lints introduced in #13750.
Run
cargo install cargo-dylint dylint-link
, then add the following entry to.vscode/settings.json
to find all places to fix:This PR fixes
and some minor and related ones.
The remainings are...
Checklist
./risedev check
(or alias,./risedev c
)Documentation
Release note
If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.