Skip to content

Commit

Permalink
feat: HTTPError.WithFields (#326)
Browse files Browse the repository at this point in the history
* feat: HTTPError.WithFields

* fix: exclude from json

* fix: add test
  • Loading branch information
Skn0tt authored Mar 3, 2022
1 parent 8b345a6 commit 35dff55
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
31 changes: 25 additions & 6 deletions router/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ import (
"github.com/bugsnag/bugsnag-go/v2"
"github.com/netlify/netlify-commons/metriks"
"github.com/netlify/netlify-commons/tracing"
"github.com/sirupsen/logrus"
)

// HTTPError is an error with a message and an HTTP status code.
type HTTPError struct {
Code int `json:"code"`
Message string `json:"msg"`
JSON interface{} `json:"json,omitempty"`
InternalError error `json:"-"`
InternalMessage string `json:"-"`
ErrorID string `json:"error_id,omitempty"`
Code int `json:"code"`
Message string `json:"msg"`
JSON interface{} `json:"json,omitempty"`
InternalError error `json:"-"`
InternalMessage string `json:"-"`
ErrorID string `json:"error_id,omitempty"`
Fields logrus.Fields `json:"-"`
}

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

// WithFields will add fields to an error message
func (e *HTTPError) WithFields(fields logrus.Fields) *HTTPError {
for key, value := range fields {
e.Fields[key] = value
}
return e
}

// WithFields will add fields to an error message
func (e *HTTPError) WithField(key string, value interface{}) *HTTPError {
e.Fields[key] = value
return e
}

func httpError(code int, fmtString string, args ...interface{}) *HTTPError {
return &HTTPError{
Code: code,
Message: fmt.Sprintf(fmtString, args...),
Fields: make(logrus.Fields),
}
}

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

switch e := err.(type) {
case *HTTPError:
log = log.WithFields(e.Fields)

e.ErrorID = errorID
if e.Code >= http.StatusInternalServerError {
notifyBugsnag = true
Expand Down
30 changes: 30 additions & 0 deletions router/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,36 @@ func TestHandleError_HTTPError(t *testing.T) {
assert.Equal(t, "internal server error: "+httpErr.InternalMessage, loggerOutput.AllEntries()[0].Message)
}

func TestHandleError_HttpErrorWithFields(t *testing.T) {
logger, loggerOutput := test.NewNullLogger()
recorder := httptest.NewRecorder()
w, r, _ := tracing.NewTracer(
recorder,
httptest.NewRequest(http.MethodGet, "/", nil),
logger,
"test",
"test",
)

httpErr := httpError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))

httpErr.WithFields(map[string]interface{}{
"a": "1",
"b": "2",
})

httpErr.WithField("c", "3")
httpErr.WithField("a", "0")

HandleError(httpErr, w, r)

require.Len(t, loggerOutput.AllEntries(), 1)
entry := loggerOutput.LastEntry()
assert.Equal(t, entry.Data["a"], "0")
assert.Equal(t, entry.Data["b"], "2")
assert.Equal(t, entry.Data["c"], "3")
}

func TestHandleError_NoLogForNormalErrors(t *testing.T) {
logger, loggerOutput := test.NewNullLogger()
recorder := httptest.NewRecorder()
Expand Down

0 comments on commit 35dff55

Please sign in to comment.