-
Notifications
You must be signed in to change notification settings - Fork 0
/
ohno.go
125 lines (113 loc) · 3.66 KB
/
ohno.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright © A.O.S, 2023.
// All Rights Reserved.
//
// author: A.O.S
// package ohno is a error context addition utility package. It is built to
// work in tandem with enums that are generated by [ohnogen]. You can however
// use this package even without that as long as you know how this package's
// internals work although it is not recommended. This package is mainly used
// to enable context addition to errors along with some simple inspection
// capabilities. It also provides structured representation in json and yaml
// formats
//
// [ohnogen]: https://pkg.go.dev/github.com/A-0-5/ohno/cmd/ohnogen
package ohno // import "github.com/A-0-5/ohno/pkg/ohno"
import (
"time"
"github.com/A-0-5/ohno/pkg/ohnoer"
"github.com/A-0-5/ohno/pkg/sourceinfo"
)
// Join combines multiple errors similar to [errors.Join] and returns a
// combined error as an [OhNoJoinError]
func Join(errs ...error) error {
n := 0
for _, err := range errs {
if err != nil {
n++
}
}
if n == 0 {
return nil
}
e := &OhNoJoinError{
Errors: make([]error, 0, n),
}
for _, err := range errs {
if err != nil {
e.Errors = append(e.Errors, err)
}
}
return e
}
// This method takes all the nested ohno errors and joins them to yield an
// [OhNoJoinError]. For example if there was a 3 level nested error all of type
// [OhNoError] then this function will convert it to an [OhNoJoinError]
// containing those 3 errors in a flat structure. For example
//
// OhNoError{
// Message: "err1"
// Cause: OhNoError{
// Message: "err2"
// Cause: OhNoError{
// Message: "err3"
// }
// }
// }
//
// will be converted to
//
// OhNoJoinError{
// Errors: []error{
// OhNoError{
// Message: "err1"
// },
// OhNoError{
// Message: "err2"
// },
// OhNoError{
// Message: "err3"
// },
// }
// }
//
// If the err parameter is not of [OhNoError] type then the err is returned
// back as it is.
// If any of the nested errors are of type [OhNoJoinError], implements the
// Unwrap() []error method or is not of type [OhNoError] then no further
// unwrapping is done the nested error is simply appended to the list and the
// unwrapping is halted.
func ConvertToJoinError(err error) error {
if ohNoErr, ok := err.(*OhNoError); ok {
return ohNoErr.drillDownAndStackUp()
}
return err
}
// This method generates a new error of [OhNoError] type. sourceInfoType
// parameter can be one of the [sourceinfo.SourceInfoType] s. callDepth is
// required if you require the Function name in the source information to be
// captured, use [sourceinfo.DefaultCallDepth] if you want the source
// information for the line where you are calling this method from. If you do
// not require source information pass sourceInfoType as [sourceinfo.NoSourceInfo]
// extra, cause, timestamp are optional and will be omitted from printing and
// marshaling. timestampLayout can be one of the standard timestamp layouts in [time package]. Default is [time.RFC3339Nano].
//
// Typically you would not need to use this directly since this would be called
// internally from the OhNo() method in the code generated by ohnogen.
//
// [time package]: https://pkg.go.dev/time#pkg-constants
func New(ohnoer ohnoer.OhNoer, message string, extra any, cause error, sourceInfoType sourceinfo.SourceInfoType, callDepth int, timeStamp time.Time, timestampLayout string) error {
if !timeStamp.IsZero() {
if timestampLayout == "" {
timestampLayout = time.RFC3339Nano
}
}
return &OhNoError{
ErrorCode: ohnoer,
Message: message,
Extra: extra,
Cause: cause,
SourceInfo: sourceinfo.GetSourceInformation(callDepth+1, sourceInfoType),
Timestamp: timeStamp,
TimestampLayout: timestampLayout,
}
}