summaryrefslogtreecommitdiffstats
path: root/third_party/rust/error-support/README.md
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/error-support/README.md
parentInitial commit. (diff)
downloadfirefox-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.md89
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.
+