Skip to content

Commit 811d243

Browse files
committed
[e] improve documentation of the package
Change-Id: Ib70298392181acdea409654e9ad5c776ae1fe3ce
1 parent 22feefe commit 811d243

3 files changed

Lines changed: 53 additions & 57 deletions

File tree

e/doc.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
1-
// Package e provides custom error type and utilities to work with it.
1+
// Package e provides a custom error type with support for error chaining and
2+
// structured metadata fields.
23
//
3-
// Its main type [Err] provides the ability to conveniently work with chains of
4-
// errors, offering methods to wrap any errors and pass metadata using fields
5-
// (fields.Field).
4+
// The main type, Err, enables convenient error wrapping and the attachment of
5+
// key-value metadata fields (fields.Field). Errors can be wrapped to add context
6+
// and enriched with fields for structured logging or diagnostics.
67
//
7-
// Example:
8-
//
9-
// var (
10-
// ErrJsonParseFailed = e.New("JSON parse failed")
11-
// )
8+
// Example: Wrapping errors with context
129
//
10+
// var ErrJSONParseFailed = e.New("JSON parse failed")
1311
// var val any
1412
// if err := json.Unmarshal([]byte(`["invalid", "json]`), &val); err != nil {
15-
// return ErrJsonParseFailed.Wrap(err) // "JSON parse failed: unexpected end of JSON input"
13+
// return ErrJSONParseFailed.Wrap(err)
14+
// // Output: "JSON parse failed: unexpected end of JSON input"
1615
// }
1716
//
18-
// Any incoming error can be granted the functionality of [Err] by using the
19-
// [From] function. Note that this is not a form of error wrapping - immediately
20-
// unwrapping such an error will not return the original one.
17+
// Example: Enriching errors with fields
18+
//
19+
// err := e.New("operation failed").WithField("user_id", 42)
20+
// // Output: "operation failed (user_id=42)"
21+
//
22+
// err = err.Wrap(e.New("db error").WithFields(fields.F("query", "SELECT *")))
23+
// // Output: "operation failed (user_id=42): db error (query=SELECT *)"
2124
//
22-
// Example:
25+
// Any error can be converted to an Err using the From function. This does not
26+
// wrap the error; unwrapping will not return the original error.
2327
//
2428
// e.From(errors.New("error")) // "error"
2529
// errors.Unwrap(e.From(errors.New("error"))) // nil
2630
//
27-
// [Err] serializes to following format:
31+
// The Err string format is:
2832
//
29-
// `<error reason>[ (fields...)][: wrapped error string]`
33+
// <reason> (fields...): <wrapped error string>
3034
//
31-
// In other words, arbitrary fields are always enclosed in parentheses, and the
32-
// wrapped error is separated with a colon and a space.
35+
// Fields are always enclosed in parentheses, and wrapped errors are separated by
36+
// a colon and space.
3337
//
34-
// Package does not provide any methods to modify existing errors, as it is
35-
// considered error-prone. Instead, any public method of the package that returns
36-
// an error - returns a new instance.
38+
// All methods that return errors create new instances; errors are immutable.
3739
//
38-
// Although [Err] implements methods [Err.Unwrap], [Err.Is], and [Err.As], these
39-
// methods are intended for internal use. These methods are marked as deprecated
40-
// to avoid confusion and improve developer experience. Consider using the
41-
// corresponding methods of the [errors] package instead.
40+
// Deprecated methods Unwrap, Is, and As are present for compatibility with the
41+
// errors package, but should not be used directly. Use the errors package
42+
// functions instead.
4243
//
43-
// To log a specific error, the package provides a convenience method [Log]. This
44-
// method creates a log entry from the specified error if it is not nil. It is
45-
// designed to be compatible with our logger abstraction - logger.Logger.
44+
// The Log function logs errors using our logger abstraction - logger.Logger,
45+
// extracting reason, wrapped error, and fields, logging them appropriately.
4646
package e

e/err.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ import (
88
"dev.gaijin.team/go/golib/fields"
99
)
1010

11+
// Err represents a custom error type that supports error chaining and structured metadata fields.
1112
type Err struct {
1213
errs []error
1314
fields fields.List
1415
}
1516

16-
// New creates new instance of Err.
17+
// New returns a new Err with the given reason and optional fields.
18+
// The returned error can be further wrapped or annotated with additional fields.
1719
func New(reason string, f ...fields.Field) *Err {
1820
return From(errors.New(reason), f...) //nolint:err113
1921
}
2022

21-
// NewFrom creates new instance of Err that wraps origin error.
23+
// NewFrom returns a new Err with the given reason, wrapping the provided error, and optional fields.
24+
// If wrapped is nil, it behaves like New.
2225
func NewFrom(reason string, wrapped error, f ...fields.Field) *Err {
2326
if wrapped == nil {
2427
return New(reason, f...)
@@ -30,9 +33,8 @@ func NewFrom(reason string, wrapped error, f ...fields.Field) *Err {
3033
}
3134
}
3235

33-
// From transforms existing error to Err. It is not wrapping operation - unwrap
34-
// will not return origin error. Passing nil to this function will result with
35-
// empty error.
36+
// From converts any error to an Err, optionally adding fields. This is not true wrapping;
37+
// unwrapping will not return the original error. Passing nil results in an Err with reason "error(nil)".
3638
func From(origin error, f ...fields.Field) *Err {
3739
if origin == nil {
3840
origin = errors.New("error(nil)") //nolint:err113
@@ -44,11 +46,8 @@ func From(origin error, f ...fields.Field) *Err {
4446
}
4547
}
4648

47-
// Wrap creates new instance of Err that wraps provided error with source one.
48-
//
49-
// Example:
50-
//
51-
// e.New("e1").Wrap(errors.New("e2")) // e1: e2
49+
// Wrap returns a new Err that wraps the provided error with the current Err as context.
50+
// Additional fields can be attached. If err is nil, it is replaced with an Err for "error(nil)".
5251
func (e *Err) Wrap(err error, f ...fields.Field) *Err {
5352
if err == nil {
5453
err = errors.New("error(nil)") //nolint:err113
@@ -60,7 +59,7 @@ func (e *Err) Wrap(err error, f ...fields.Field) *Err {
6059
}
6160
}
6261

63-
// Error returns string representation of the error.
62+
// Error returns the string representation of the Err, including reason, fields, and wrapped errors.
6463
func (e *Err) Error() string {
6564
b := &strings.Builder{}
6665
writeTo(b, e)
@@ -96,31 +95,31 @@ func writeTo(b *strings.Builder, err error) {
9695
}
9796
}
9897

99-
// Clone creates a new instance of Err with the same error, wrapped error, and
100-
// cloned fields container.
98+
// Clone returns a new Err with the same error, wrapped error, and a cloned fields container.
10199
func (e *Err) Clone() *Err {
102100
return &Err{
103101
errs: slices.Clone(e.errs),
104102
fields: slices.Clone(e.fields),
105103
}
106104
}
107105

108-
// WithFields creates new error with source error as origin and provided fields as its fields.
106+
// WithFields returns a new Err with the same error and the provided fields.
109107
func (e *Err) WithFields(f ...fields.Field) *Err {
110108
return From(e, f...)
111109
}
112110

113-
// WithField alike [Err.WithFields], but creates an error with single field added.
111+
// WithField returns a new Err with the same error and a single additional field.
114112
func (e *Err) WithField(key string, val any) *Err {
115113
return e.WithFields(fields.F(key, val))
116114
}
117115

118-
// Fields returns fields of the error.
116+
// Fields returns the metadata fields attached to the Err.
119117
func (e *Err) Fields() fields.List {
120118
return e.fields
121119
}
122120

123-
// Reason returns reason string of the error without fields and wrapped errors.
121+
// Reason returns the reason string of the Err, without fields or wrapped errors.
122+
// If the Err is nil, returns "(*e.Err)(nil)". If empty, returns "(*e.Err)(empty)".
124123
func (e *Err) Reason() string {
125124
if e == nil {
126125
return "(*e.Err)(nil)"
@@ -133,8 +132,9 @@ func (e *Err) Reason() string {
133132
return e.errs[0].Error()
134133
}
135134

136-
// Unwrap implemented only for purposes of compatibility with [errors.Is] and
137-
// [errors.As] methods.
135+
// Unwrap returns the underlying errors for compatibility with errors.Is and errors.As.
136+
//
137+
// Deprecated: This method is for internal use only. Prefer using the errors package directly.
138138
func (e *Err) Unwrap() []error {
139139
return e.errs
140140
}

e/log.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,20 @@ import (
44
"dev.gaijin.team/go/golib/fields"
55
)
66

7+
// ErrorLogger defines a function that logs an error message, an error, and optional fields.
78
type ErrorLogger func(msg string, err error, fs ...fields.Field)
89

9-
// Log logs the provided error using the given logger.
10+
// Log logs the provided error using the given ErrorLogger function.
1011
//
11-
// If the error is nil, the function does nothing.
12-
//
13-
// If the error is of type [Err], its reason is used as the error message, the
14-
// wrapped error is passed as the actual error, and the error's fields are passed
15-
// as log fields.
16-
//
17-
// Otherwise, err.Error() is used as the error message, and nil is passed as the
18-
// actual error.
12+
// If err is nil, Log does nothing. If err is of type Err, its reason is used as the log message,
13+
// the wrapped error is passed as the error, and its fields are passed as log fields.
14+
// For other error types, err.Error() is used as the message and nil is passed as the error.
1915
func Log(err error, f ErrorLogger) {
2016
if err == nil {
2117
return
2218
}
2319

24-
// we're not interested in wrapped error, therefore we're only typecasting it.
20+
// We're not interested in wrapped error, therefore we're only typecasting it.
2521
if e, ok := err.(*Err); ok { //nolint:errorlint
2622
var wrapped error
2723
if len(e.errs) > 1 {

0 commit comments

Comments
 (0)