Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

## [0.8.0] - 2025-10-14

### Added
- Recognised `#[provide(ref = ..., value = ...)]` on struct and enum fields,
allowing derived errors to surface domain telemetry through
`std::error::Request` alongside backtraces.

### Changed
- `masterror-derive` now generates `provide` implementations whenever custom
telemetry is requested, forwarding `Request` values to sources and invoking
`provide_ref`/`provide_value` with proper `Option` handling.

### Tests
- Extended the `error_derive` integration suite with regressions covering
telemetry provided by structs, tuple variants and optional fields, including
both reference and owned payloads.

### Documentation
- Documented the `#[provide(...)]` attribute in the README with examples showing
reference and owned telemetry as well as optional fields.

## [0.7.0] - 2025-10-13

### Added
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "masterror"
version = "0.7.0"
version = "0.8.0"
rust-version = "1.90"
edition = "2024"
license = "MIT OR Apache-2.0"
Expand Down Expand Up @@ -49,7 +49,7 @@ turnkey = []
openapi = ["dep:utoipa"]

[workspace.dependencies]
masterror-derive = { version = "0.3.0", path = "masterror-derive" }
masterror-derive = { version = "0.4.0", path = "masterror-derive" }
masterror-template = { version = "0.2.0", path = "masterror-template" }

[dependencies]
Expand Down
64 changes: 57 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ Stable categories, conservative HTTP mapping, no `unsafe`.

~~~toml
[dependencies]
masterror = { version = "0.7.0", default-features = false }
masterror = { version = "0.8.0", default-features = false }
# or with features:
# masterror = { version = "0.7.0", features = [
# masterror = { version = "0.8.0", features = [
# "axum", "actix", "openapi", "serde_json",
# "sqlx", "sqlx-migrate", "reqwest", "redis",
# "validator", "config", "tokio", "multipart",
Expand Down Expand Up @@ -66,10 +66,10 @@ masterror = { version = "0.7.0", default-features = false }
~~~toml
[dependencies]
# lean core
masterror = { version = "0.7.0", default-features = false }
masterror = { version = "0.8.0", default-features = false }

# with Axum/Actix + JSON + integrations
# masterror = { version = "0.7.0", features = [
# masterror = { version = "0.8.0", features = [
# "axum", "actix", "openapi", "serde_json",
# "sqlx", "sqlx-migrate", "reqwest", "redis",
# "validator", "config", "tokio", "multipart",
Expand Down Expand Up @@ -211,6 +211,56 @@ let as_app: AppError = missing.into();
assert_eq!(as_app.message.as_deref(), Some("missing resource 7"));
~~~

#### Provide custom telemetry

Fields can expose structured telemetry to `std::error::Request` consumers by
annotating them with `#[provide(...)]`. The attribute accepts `ref = <Type>` to
publish borrowed values via `Request::provide_ref` and `value = <Type>` to clone
and forward owned data with `Request::provide_value`. Both specifiers are
optional, enabling one field to provide different representations. Optional
fields only emit telemetry when they contain a value, mirroring the
backtrace-handling behaviour of `thiserror`.

When the crate is compiled with `--cfg error_generic_member_access` (required by
the current unstable `std::error::request_*` helpers), the derive generates a
`provide` implementation that forwards the `Request` to any `#[source]` field
before yielding the annotated telemetry:

~~~rust
use masterror::Error;

#[derive(Clone, Debug, PartialEq, Eq)]
struct Snapshot(&'static str);

#[derive(Debug, Error)]
#[error("snapshot {0:?}")]
struct SnapshotError(
#[provide(ref = Snapshot, value = Snapshot)]
Snapshot
);

#[derive(Debug, Error)]
#[error("optional telemetry {0:?}")]
struct MaybeSnapshot(
#[provide(ref = Snapshot)]
Option<Snapshot>
);

#[cfg(error_generic_member_access)]
{
let err = SnapshotError(Snapshot("trace"));
let borrowed = std::error::request_ref::<Snapshot>(&err).unwrap();
assert_eq!(borrowed, &Snapshot("trace"));
let owned = std::error::request_value::<Snapshot>(&err).unwrap();
assert_eq!(owned, Snapshot("trace"));

let maybe = MaybeSnapshot(Some(Snapshot("span")));
assert!(std::error::request_ref::<Snapshot>(&maybe).is_some());
let empty = MaybeSnapshot(None);
assert!(std::error::request_ref::<Snapshot>(&empty).is_none());
}
~~~

#### Formatter traits

Placeholders default to `Display` (`{value}`) but can opt into richer
Expand Down Expand Up @@ -435,13 +485,13 @@ assert_eq!(resp.status, 401);
Minimal core:

~~~toml
masterror = { version = "0.7.0", default-features = false }
masterror = { version = "0.8.0", default-features = false }
~~~

API (Axum + JSON + deps):

~~~toml
masterror = { version = "0.7.0", features = [
masterror = { version = "0.8.0", features = [
"axum", "serde_json", "openapi",
"sqlx", "reqwest", "redis", "validator", "config", "tokio"
] }
Expand All @@ -450,7 +500,7 @@ masterror = { version = "0.7.0", features = [
API (Actix + JSON + deps):

~~~toml
masterror = { version = "0.7.0", features = [
masterror = { version = "0.8.0", features = [
"actix", "serde_json", "openapi",
"sqlx", "reqwest", "redis", "validator", "config", "tokio"
] }
Expand Down
2 changes: 1 addition & 1 deletion masterror-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "masterror-derive"
rust-version = "1.90"
version = "0.3.0"
version = "0.4.0"
edition = "2024"
license = "MIT OR Apache-2.0"
repository = "https://github.com/RAprogramm/masterror"
Expand Down
Loading
Loading