Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions json_formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ type JSONFormatter struct {
PrettyPrint bool
}

func errorsArrayToStrings(errs []error) []string {
strs := make([]string, len(errs))
for i, err := range errs {
strs[i] = err.Error()
}
return strs
}

// Format renders a single log entry
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
data := make(Fields, len(entry.Data)+4)
Expand All @@ -68,6 +76,8 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
// Otherwise errors are ignored by `encoding/json`
// https://github.com/sirupsen/logrus/issues/137
data[k] = v.Error()
case []error:
data[k] = errorsArrayToStrings(v)
Comment on lines +79 to +80

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly thinking out loud here; now that go stdlib provides native support for "multi-errors" through errors.Join, I wonder if this is something that would be better fixed in the code using logrus.

i.e.; instead of WithField("errors", []error{...}), to use WithError(errors.Join(errs....)) (or similar)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tricky bit is that logrus will (probably) never be able to fully cover all scenarios; if such a []error (or a regular error) would be part of a struct that's set as field; it would probably still produce a non-string output for the error(s).

default:
data[k] = v
}
Expand Down
32 changes: 31 additions & 1 deletion json_formatter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,37 @@ func TestErrorNotLost(t *testing.T) {
}

if entry["error"] != "wild walrus" {
t.Fatal("Error field not set")
t.Fatal("Error field not correct: ", entry["error"])
}
}

func TestErrorsNotLost(t *testing.T) {
formatter := &JSONFormatter{}

b, err := formatter.Format(
WithField("errors", []error{
errors.New("wild walrus"),
errors.New("mild wombat"),
}),
)
if err != nil {
t.Fatal("Unable to format entry: ", err)
}

entry := make(map[string]interface{})
err = json.Unmarshal(b, &entry)
if err != nil {
t.Fatal("Unable to unmarshal formatted entry: ", err)
}

fmt.Println(string(b))

errs, ok := entry["errors"].([]interface{})
if !ok {
t.Fatalf("Errors field type not correct: %T", entry["errors"])
}
if errs[0] != "wild walrus" || errs[1] != "mild wombat" {
t.Fatal("Error field not correct: ", entry["errors"])
}
}

Expand Down