generated from xmidt-org/.go-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errorFielder.go
131 lines (110 loc) · 3.23 KB
/
errorFielder.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
126
127
128
129
130
131
package erraux
import (
"errors"
"net/http"
)
const (
codeFieldName = "code"
causeFieldName = "cause"
)
// ErrorFielder can be implemented by errors to produce custom fields
// in the rendered JSON.
type ErrorFielder interface {
// ErrorFields can return any desired fields that flesh out the error.
// The returned slice is in the same format as Fields.Add.
ErrorFields() []interface{}
}
// fieldsFor is a helper that determines the extra JSON fields for an
// error. If err or anything in its chain implements ErrorFielder,
// those fields are used. Otherwise, this function returns an empty slice.
func fieldsFor(err error) (fields []interface{}) {
var ef ErrorFielder
if errors.As(err, &ef) {
fields = ef.ErrorFields()
}
return
}
// Fields holds JSON fields for an error.
type Fields map[string]interface{}
// NewFields constructs the minimal JSON fields for an error.
// If code is less than 100 (the lowest value HTTP status code),
// then http.StatusInternalServerError is used instead.
func NewFields(code int, cause string) Fields {
if code < 100 {
code = http.StatusInternalServerError
}
return Fields{
codeFieldName: code,
causeFieldName: cause,
}
}
// Code returns the status code for this set of fields.
// This method returns 0 if there is no code or if the code
// is not an int.
func (f Fields) Code() int {
c, _ := f[codeFieldName].(int)
return c
}
// SetCode updates the code field.
func (f Fields) SetCode(code int) {
f[codeFieldName] = code
}
// HasCause tests if this Fields has a cause.
func (f Fields) HasCause() bool {
_, ok := f[causeFieldName]
return ok
}
// Cause returns the cause for this set of fields.
// This method returns the empty string if there is no cause
// or if the cause is not a string.
func (f Fields) Cause() string {
c, _ := f[causeFieldName].(string)
return c
}
// SetCause updates the cause field.
func (f Fields) SetCause(cause string) {
f[causeFieldName] = cause
}
// Clone returns a distinct, shallow copy of this Fields instance.
func (f Fields) Clone() Fields {
c := make(Fields, len(f))
for k, v := range f {
c[k] = v
}
return c
}
// Merge merges the fields from the given Fields into this instance.
func (f Fields) Merge(more Fields) {
for k, v := range more {
f[k] = v
}
}
// Add adds a variadic set of names and values to this fields.
//
// Each even-numbered item in this method's variadic arguments must be a string, or
// this method will panic. Each odd-numbered item is paired as the value of the preceding
// name. If there are an odd number of items, the last item must be a string and it
// is interpreted as having an nil value.
func (f Fields) Add(namesAndValues ...interface{}) {
for i, j := 0, 1; i < len(namesAndValues); i, j = i+2, j+2 {
name := namesAndValues[i].(string)
var value interface{}
if j < len(namesAndValues) {
value = namesAndValues[j]
}
f[name] = value
}
}
// Append does the reverse of Add. This method flattens
// a Fields into a sequence of {name1, value1, name2, value2, ...} values.
func (f Fields) Append(nav []interface{}) []interface{} {
if cap(nav) < len(nav)+len(f) {
grow := make([]interface{}, 0, len(nav)+len(f))
grow = append(grow, nav...)
nav = grow
}
for k, v := range f {
nav = append(nav, k, v)
}
return nav
}