Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error value in log.Fields disappears when using JSON formatter #137

Closed
rsterbin opened this issue Feb 26, 2015 · 4 comments
Closed

Error value in log.Fields disappears when using JSON formatter #137

rsterbin opened this issue Feb 26, 2015 · 4 comments

Comments

@rsterbin
Copy link

When passing an error as a field and using the JSON formatter, the error message is omitted:

package main

import "errors"
import log "github.com/Sirupsen/logrus"

func main() {
    err := errors.New("Here is an error message")
    log.WithFields(log.Fields{
        "error": err,
    }).Error("Logging without json")
    log.SetFormatter(&log.JSONFormatter{})
    log.WithFields(log.Fields{
        "error": err,
    }).Error("Logging with json")
}

Results:

ERRO[0000] Logging without json                          error=Here is an error message
{"error":{},"level":"error","msg":"Logging with json","time":"2015-02-26T20:32:02Z"}
@hasryan
Copy link

hasryan commented Mar 4, 2015

I ran into the same issue.

From what I can tell the TextFormatter handles errors specially (rendering the output of Error()): https://github.com/Sirupsen/logrus/blob/c0f7e35ed2e48f188c37581b4b743cf7383f85c6/text_formatter.go#L127

While the JSONFormatter does no such thing prior to encoding: https://github.com/Sirupsen/logrus/blob/2835e150d968bd0cd8acaed3a97016342bcb2dea/json_formatter.go#L13-L21

I think it makes sense to do the same thing in the JSONFormatter, but for the time being I'm carefully passing err.Error() rather than the raw err.

@rsterbin
Copy link
Author

rsterbin commented Mar 4, 2015

I've got a pull request out for this issue doing something a little different from the text formatter -- would be great to know if that solution meets your needs as well.

Right now my workaround is using a hook to add the error message, because sometimes a custom error has extra fields that are correctly picked up by json.Marshal (e.g., net.OpError).

sirupsen added a commit that referenced this issue Mar 19, 2015
@dankinder
Copy link

dankinder commented Apr 27, 2016

Hi there, just wondering what version of go this was an issue one? In golang 1.6 @rsterbin's original issue does not seem to happen:

ERRO[0000] Logging without json                          error=Here is an error message
{"error":"Here is an error message","level":"error","msg":"Logging with json","time":"2016-04-27T08:38:59-07:00"}

This is relevant because one thing we would like to do is return custom errors that implement MarshalJSON() as well as Error(), so that they can be treated like plain old error types but also be serialized intelligently in logrus messages.

At the moment this particular patch prevents this. If we have a type that implements Error() then the current logrus code seems to see it as an error type and call Error() on it, which stringify's it.

Example:

package main                                                                                                                

import log "github.com/Sirupsen/logrus"                                                                                     

type ErrorFields map[string]interface{}                                                                                     

func (e *ErrorFields) MarshalJSON() ([]byte, error) {                                                                       
    return []byte("using the MarshalJSON() call"), nil                                                                      
}                                                                                                                           

func (e *ErrorFields) Error() string {                                                                                      
    return "using the Error() call"                                                                                         
}                                                                                                                           

func main() {                                                                                                               
    err := &ErrorFields{}                                                                                                   
    log.SetFormatter(&log.JSONFormatter{})                                                                                  
    log.WithFields(log.Fields{                                                                                              
        "whatever": err,                                                                                                    
    }).Info("Logging with json")                                                                                            
}

@dankinder
Copy link

Nevermind my previous comment, I realized it doesn't quite match what @rsterbin posted and only works because of the type I am using. Turns out it's because errorString (returned by error.New) does not export the error and so it won't marshal it.

golang/go#10748 is relevant and golang/go#5161, if actually done, could help here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants