Releases: repenguin22/errtrail
Releases · repenguin22/errtrail
Release list
v1.3.2
Follow-up on the v1.3.1 review-round batch — two spots the sweep still
missed.
- Fixed
TestErrorStructSize(added in v1.3.1 to pin the 144 B layout
fix) asserted 144 unconditionally, failing on any 32-bit target:uintptr
and slice/string header words are 4 bytes there, andtime.Duration
(retryDelay) aligns to 4 rather than 8 — hand-computed and confirmed at
80 B forGOARCH=386(no 32-bit CI runner to run it on directly, but
go vet/go test -ccross-compile cleanly). The test now branches on
unsafe.Sizeof(uintptr(0)). Test-only; no library behavior changed on
any platform. - Docs Three more enumerations of the client-visible channels missed
the retry delay: DESIGN.md'sWithoutPublicedge-case-table row, the
README "at the source" intro paragraph, anddetailed's (format.go)
internal comment on what%+vgathers.
v1.3.1
External review round 7 findings.
- Fixed
NewSkip/WrapSkipwith askiplarge enough that3+skip
overflowsint(e.g.math.MaxInt) recorded a bogus frame near the top
of the call stack instead of the documented "unknown" fallback for a skip
past the stack top.callernow guards the overflow explicitly. - Changed
Error's allocation drops back to 144 B (was 160 B since
v1.3.0):noPublicBelowmoved right aftercodein the struct, filling
its padding byte instead of adding one at the end. Pure layout — no
behavior or API change. Pinned by a struct-size test; README/doc.go
benchmarks and cost notes updated. - Changed
LogValueno longer costs allocations for public fields and
field violations it never emits —collect's internal signature gained
anincludePublicflag,falseforLogValue,truefor%+v. Same
chain-walk count, just fewer discarded slices. - Docs The "exactly three channels" wording missed by the v1.3.0 sweep
—doc.go's package-overview bullet,DESIGN.md's header/struct
sketch/test-plan lines, and aninspect_test.gocomment — now says four.
v1.3.0
Additive API only — no behavior change for existing code; construction
allocation grows one size class (ROADMAP §5).
- Added
(*Error).WithRetryDelay(d)andLookupRetryDelay(err)— the
fourth client-visible channel, carrying a per-error dynamic retry
delay (a rate limiter's actual time to the next token) that
grpcerr.ToStatusemits as theRetryInfodetail, beating the static
registry delay (RetryAfter). Outermost delay wins; blocked below a
WithoutPublicbarrier; excluded fromLogValue; shown as%+v's new
public.retry:line. A non-positive delay is a no-op — the input is a
computed value and "retry after zero" carries no recommendation
(deliberately not a panic, unlike registration-timeRetryAfter). The
"exactly three channels" contract wording moves to four across the docs.
problemdeliberately still emits noRetry-Afterheader — the README
shows the two-line handler pattern viaLookupRetryDelay. - Changed The
Errorstruct grew by the delay field: construction is
now 160 B (was 144 B), still ~200ns / 1 alloc. README benchmarks updated.
v1.2.0
Additive only — no behavior changes for existing code (ROADMAP §4).
- Added
NewSkip(skip, code, msg)andWrapSkip(skip, err, msg)—
caller-skip constructors for error factories (external review round 6). A
helper likeapperr.NotFound(msg)built on plainNewrecords its own
line in every trace;skip=1points the frame at the factory's caller
instead (zapAddCallerSkipprecedent). Separate functions, so the
New/Wraphot path is unchanged.skip=0is exactlyNew/Wrap; a
skip past the top of the stack records the"unknown"frame; a negative
skip panics. Core coverage reaches 100% — the over-skip test exercises
the previously unreachablecaller()failure branch.
v1.1.5
Documentation only — no code change (external review round 6).
- Docs External review round 6:
problem.Writenotes that invalid UTF-8
in public strings is replaced with U+FFFD by encoding/json itself (the HTTP
boundary tolerates bytes the gRPC transport refuses); DESIGN.md §9 carries
the poisoned-message caveat recorded in grpcerr's entry below.
v1.1.4
A display fix plus review-round docs and tests (Gemini finding 3; external
review round 5).
- Fixed
Frame.String()no longer renders a bogus" (:0)"location for
unresolved frames (bothFileandLinezero — e.g. the"unknown"
sentinel a zero-valueErrorresolves to). A frame with either part set
still prints the location. - Docs External-review (round 5) drift swept: DESIGN.md §9's
RetryDelay
spec now carries the v1.1.2 CheckValid gate (delays outside the protobuf
Duration range are rejected, not saturated); the §6 verb table gains the
unknown-verb fallback row;problem.Writedocuments that a panicking
MarshalJSONon a public field value propagates (matching encoding/json). - Tests Previously uncovered branches pinned:
%+von a nil*Error
("<nil>"), the unknown-verb%vfallback, andWrapf's non-nil path.
otelerr/v1.0.1
External review round 7 finding.
- Fixed
RecordSpanno longer lets aWithattr sharing the reserved
"errtrail.code"key duplicate the taxonomy attribute on the exported
exception event. A duplicate key's resolution (first-wins, last-wins, or
an array) varies by tracing backend — an accidental or hostile attr named
errtrail.codecould silently corrupt the one attribute alerts and
dashboards key off of. The attr is now dropped; the real code always
wins. No core requirement change.
grpcerr/v1.3.0
Dynamic retry pushback (ROADMAP §5). Requires core v1.3.0.
- Changed The
RetryInfodetail now prefers the error's own delay
(errtrail.WithRetryDelay— dynamic pushback) over the code's registered
staticRetryAfterdelay; errors without a per-error delay keep the
registry behavior exactly. A delay below aWithoutPublicbarrier is not
exposed, while the registry delay — code configuration, not error data —
still applies. Pinned end-to-end over bufconn: the dynamic value reaches
the client'sRetryDelayreader. Requires core ≥ v1.3.0.
grpcerr/v1.2.0
Frame-placement improvement (ROADMAP §4). Requires core v1.2.0.
- Changed
FromError/FromStatusrecord the frame at their caller
(via core's newWrapSkip(1)), so traces start where the wire error
entered your code. The documented workaround — "the frame points inside
grpcerr; wrap the result at the call site" — is retired; an existing
errtrail.Wrapat the call site keeps working and simply adds one more
frame. Requires core ≥ v1.2.0.
grpcerr/v1.1.5
Documentation and tests only — no code change (external review round 6).
- Docs External review round 6 (measured over bufconn): an invalid-UTF-8
public message sits outside v1.1.4's per-detail isolation — it lives on
the Status proto itself, so the transport cannot marshal the
grpc-status-details-bin trailer and the client receives code+message but
zero details (custom-code recovery degrades to the numeric wire code;
only grpclog sees the failure).ToStatusdocuments the hazard and the
utf8.ValidStringguidance;FromErrorwarns that the wire message can
carry raw non-UTF-8 bytes, so echoing it unvalidated intoWithPublic
poisons your own response's details. Guarding it in code was considered
and rejected (ROADMAP): the trailer is the transport's to build, and
rewriting the message would be silent mutation. - Tests A standing test pins both halves of the mechanism: the
in-process attach succeeds (3 details) whileproto.Marshal(st.Proto())
fails on the poisoned message — so a grpc-go/protobuf change altering
either half is noticed.