I'm using the logrus package for logging in a Go project. To display key value pairs in logs, the docs give the following format:
log.WithFields(log.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
Instead of using string keys manually in each log, I wish to use a common struct across all logs (to avoid chances of typos in keys).
Something like this:
type LogMessage struct {
Status bool `json:"status"`
Message string `json:"message"`
}
log.WithFields(&LogMessage {Status: false, Message: "Error User Already Exists"}).Info("User Creation Failed.")
The log output should be as :
time="2015-03-26T01:27:38-04:00" level=info msg="User Creation Failed." status=false message="Error User Already Exists"
How can this be implemented ?
Thanks for any help !
CodePudding user response:
You cannot pass a struct to WithFields()
. It takes Fields
type (which is basically map[string]interface{}
). To avoid making mistakes in common key names you can create constants - that way if you make typo in constant name code won't even compile (and in the end it will be less verbose to write than passing a struct):
const Status = "status"
const Message = "message"
//...
log.WithFields(log.Fields{Status: true, Message: "a message"}).Info("foo")
To implement exactly what you want you will need to convert struct to a map before passing to WithFields()
:
import (
structs "github.com/fatih/structs" // ARCHIVED
log "github.com/sirupsen/logrus"
)
//...
type LogMessage struct {
Status bool `json:"status"`
Message string `json:"message"`
}
log.WithFields(structs.Map(&LogMessage{Status: true, Message: "a message"})).Info("foo")
// Will output:
// time="2009-11-10T23:00:00Z" level=info msg=foo Message="a message" Status=true
(Note: I used library "structs" that is archived just to demonstrate principle. Also reflection required to do conversion adds performance cost so I wouldn't use this in performance-critical parts of program).
CodePudding user response:
you can use a custom wrapping function inside which you can set your field keys.
https://play.golang.org/p/H22M63kn8Jb
package main
import (
log "github.com/sirupsen/logrus"
)
func LogMyMessages(messageStruct *myMessageStruct) {
log.WithFields(log.Fields{"status": messageStruct.Status, "message": messageStruct.Message}).Info("foo")
}
type myMessageStruct struct {
Message string
Status bool
}
func main() {
LogMyMessages(&myMessageStruct{Status: true, Message: "test message"})
}
gives a message like so
time="2009-11-10T23:00:00Z" level=info msg=foo message="test message" status=true