Skip to content

Commit 35dff55

Browse files
authored
feat: HTTPError.WithFields (#326)
* feat: HTTPError.WithFields * fix: exclude from json * fix: add test
1 parent 8b345a6 commit 35dff55

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

router/errors.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ import (
88
"github.com/bugsnag/bugsnag-go/v2"
99
"github.com/netlify/netlify-commons/metriks"
1010
"github.com/netlify/netlify-commons/tracing"
11+
"github.com/sirupsen/logrus"
1112
)
1213

1314
// HTTPError is an error with a message and an HTTP status code.
1415
type HTTPError struct {
15-
Code int `json:"code"`
16-
Message string `json:"msg"`
17-
JSON interface{} `json:"json,omitempty"`
18-
InternalError error `json:"-"`
19-
InternalMessage string `json:"-"`
20-
ErrorID string `json:"error_id,omitempty"`
16+
Code int `json:"code"`
17+
Message string `json:"msg"`
18+
JSON interface{} `json:"json,omitempty"`
19+
InternalError error `json:"-"`
20+
InternalMessage string `json:"-"`
21+
ErrorID string `json:"error_id,omitempty"`
22+
Fields logrus.Fields `json:"-"`
2123
}
2224

2325
// BadRequestError creates a 400 HTTP error
@@ -79,10 +81,25 @@ func (e *HTTPError) WithInternalMessage(fmtString string, args ...interface{}) *
7981
return e
8082
}
8183

84+
// WithFields will add fields to an error message
85+
func (e *HTTPError) WithFields(fields logrus.Fields) *HTTPError {
86+
for key, value := range fields {
87+
e.Fields[key] = value
88+
}
89+
return e
90+
}
91+
92+
// WithFields will add fields to an error message
93+
func (e *HTTPError) WithField(key string, value interface{}) *HTTPError {
94+
e.Fields[key] = value
95+
return e
96+
}
97+
8298
func httpError(code int, fmtString string, args ...interface{}) *HTTPError {
8399
return &HTTPError{
84100
Code: code,
85101
Message: fmt.Sprintf(fmtString, args...),
102+
Fields: make(logrus.Fields),
86103
}
87104
}
88105

@@ -102,6 +119,8 @@ func HandleError(err error, w http.ResponseWriter, r *http.Request) {
102119

103120
switch e := err.(type) {
104121
case *HTTPError:
122+
log = log.WithFields(e.Fields)
123+
105124
e.ErrorID = errorID
106125
if e.Code >= http.StatusInternalServerError {
107126
notifyBugsnag = true

router/errors_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,36 @@ func TestHandleError_HTTPError(t *testing.T) {
122122
assert.Equal(t, "internal server error: "+httpErr.InternalMessage, loggerOutput.AllEntries()[0].Message)
123123
}
124124

125+
func TestHandleError_HttpErrorWithFields(t *testing.T) {
126+
logger, loggerOutput := test.NewNullLogger()
127+
recorder := httptest.NewRecorder()
128+
w, r, _ := tracing.NewTracer(
129+
recorder,
130+
httptest.NewRequest(http.MethodGet, "/", nil),
131+
logger,
132+
"test",
133+
"test",
134+
)
135+
136+
httpErr := httpError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
137+
138+
httpErr.WithFields(map[string]interface{}{
139+
"a": "1",
140+
"b": "2",
141+
})
142+
143+
httpErr.WithField("c", "3")
144+
httpErr.WithField("a", "0")
145+
146+
HandleError(httpErr, w, r)
147+
148+
require.Len(t, loggerOutput.AllEntries(), 1)
149+
entry := loggerOutput.LastEntry()
150+
assert.Equal(t, entry.Data["a"], "0")
151+
assert.Equal(t, entry.Data["b"], "2")
152+
assert.Equal(t, entry.Data["c"], "3")
153+
}
154+
125155
func TestHandleError_NoLogForNormalErrors(t *testing.T) {
126156
logger, loggerOutput := test.NewNullLogger()
127157
recorder := httptest.NewRecorder()

0 commit comments

Comments
 (0)