diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/error-support/README.md | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/error-support/README.md')
-rw-r--r-- | third_party/rust/error-support/README.md | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/third_party/rust/error-support/README.md b/third_party/rust/error-support/README.md new file mode 100644 index 0000000000..52e6f0efde --- /dev/null +++ b/third_party/rust/error-support/README.md @@ -0,0 +1,89 @@ +# Application error handling support + +This crate provides support for other crates to effectively report errors. +Because app-services components get embedded in various apps, written in +multiple languages, we face several challenges: + + - Rust stacktraces are generally not available so we often need to provide + extra context to help debug where an error is occuring. + - Without stack traces, Sentry and other error reporting systems don't do a + great job at auto-grouping errors together, so we need to manually group them. + - We can't hook directly into the error reporting system or even depend on a + particular error reporting system to be in use. This means the system + needs to be simple and flexible enough to plug in to multiple systems. + +## Breadcrumbs as context + +We use a breadcrumb system as the basis for adding context to errors. +Breadcrumbs are individual messages that form a log-style stream, and the most +recent breadcrumbs get attached to each error reported. There are a lot of +other ways to provide context to an error, but we just use breadcrumbs for +everything because it's a relatively simple system that's easy to hook up to +error reporting platforms. + +## Basic error reporting tools + +Basic error reporting is handled using several macros: + + - `report_error!()` creates an error report. It inputs a `type_name` as the + first parameter, and `format!` style arguments afterwards. `type_name` is + used to group errors together and show up as error titles/headers. Use the + format-style args to create is a long-form description for the issue. Most + of the time you won't need to call this directly, since can automatically + do it when converting internal results to public ones. However, it can be + useful in the case where you see an error that you want + to report, but want to try to recover rather than returning an error. + - `breadcrumb!()` creates a new breadcrumb that will show up on future errors. + - `trace_error!()` inputs a `Result<>` and creates a breadcrumb if it's an + `Err`. This is useful if when you're trying to track down where an error + originated from, since you can wrap each possible source of the error with + `trace_error!()`. `trace_error!()` returns the result passed in to it, + which makes wrapping function calls easy. + + +## Public/Internal errors and converting between them + +Our components generally create 2 error enums: one for internal use and one for +the public API. They are typically named `Error` and +`[ComponentName]ApiError`. The internal error typically carries a lot of +low-level details and lots of variants which is useful to us app-services +developers. The public error typically has less variants with the variants +often just storing a reason string rather than low-level error codes. There +are also two `Result<>` types that correspond to these two errors, typically +named `Result` and `ApiResult`. + +This means we need to convert from internal errors to public errors, which has +the nice side benefit of giving us a centralized spot to make error reports for +selected public errors. This is done with the `ErrorHandling` type and +`GetErrorHandling` trait in `src/handling.rs`. The basic system is that you +convert between one error to another and choose if you want to report the error +and/or log a warning. When reporting an error you can choose a type name to +group the error with. This system is extremely flexible, since you can inspect +the internal error and use error codes or other data to determine if it should +be reported or not, which type name to report it with, etc. Eventually we also +hope to allow expected errors to be counted in telemetry (think things like +network errors, shutdown errors, etc.). + +To assist this conversion, the `handle_error!` macro can be used to +automatically convert between `Result` and `ApiResult` using +`GetErrorHandling`. Note that this depends on having the `Result` type +imported in your module with a `use` statement. + +See the `logins::errors` and `logins::store` modules for an example of how this +all fits together. + +## ⚠️ Personally Identifiable Information ⚠️ + +When converting internal errors to public errors, we should ensure that there +is no personally identifying information (PII) in any error reports. We should +also ensure that no PII is contained in the public error enum, since consumers +may end up uses those for their own error reports. + +We operate on a best-effort basis to ensure this. Our error details often come +from an error from one of our dependencies, which makes it very diffucult to be +completely sure though. For example, `rusqlite::Error` could include data from +a user's database in their errors, which would then appear in our error +variants. However, we've never seen that in practice so we are comfortable +including the `rusqlite` error message in our error reports, without attempting +to sanitize them. + |