The follow string is that I want to log to file:
{"name": "test", "id": "123xx"}
When I log this string to file , no matter the json format or text format, logrus auto add a backslash('\') before double quotes. like following:
{\"name\": \"test\", \"id\": \"123xx\"}
But I don't want backslash. How can I remove it?
Do you have an answers ? I met a same issue .
I modify it , you can try https://github.com/Wang-Kai/logrus
I don't think this change should be made. The concept of passing a JSON as log message is not right. You don't know who's gonna have to read your log entry, so adding backslashes keeps everyone safe. If we have a JSON with multiple properties, one of them might be the message but the others are just fields.
In case to receive a JSON and wanting to add it to the log entry, you can easily write a wrapper to make your life easier. logrus.Fields is just a map[string]interface{} object so we can do:
func getFields(jsonMessage string) logrus.Fields {
fields := logrus.Fields{}
json.Unmarshal([]byte(jsonMessage), &fields)
return fields
}
logger.WithFields(getFields(jsonMessage)).Info("This can be empty if not needed")
You can even write something more powerful, depending on your needs:
func getFields(jsonMessage string) (string, logrus.Fields) {
fields := logrus.Fields{}
err := json.Unmarshal([]byte(jsonMessage), &fields)
if err == nil {
message := fields["messageKey"]
delete(fields, "messageKey")
return message, fields
}
return jsonMessage, fields
}
This will print something more maningful:
INFO[0000] Test message id=123xx name=test
PS.- Maybe Logrus could implement importing the fields from a json string.
I think it is useful in some case .
For example , i want to log every request , fields including trace_id 銆乮p銆乁serAgent銆乺equest body and so on . So the perfect log like :
INFO[2018-27-03 20:05:04] Request TraceID=122000006905486900 IP=192.168.34.34 UserAgent=HTTPie/0.9.3 ReqBody={"name": "test", "id": "123xx"}
It is comfortable to check every request log. The code maybe like that :
func handleCommonReq(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
...
log.WithFields(log.Fields{
"TraceID": r.Context.Value("trace_id"),
"IP": strings.Split(r.RemoteAddr, ":")[0],
"Body": string(reqBody[:]),
UserAgent": r.UserAgent(),
})
...
}
My request body is JSON like data, so if double quotes prefix with backslash is so ugly in log file . Your solution is so smart, but it only can translate JSON data to map[string]interface{} , maybe it can't meet my needs .
Your solution in your last comment is perfect. The problem I see with the pull request is that the changes requested to meet your needs are going to affect other users. There's a function in Logrus to detect if the message needs quoting and your change literally disables that (leaving unused code behind as well).
As far as I can see there's two/three options here.
The easy one is to create your own MyUnsafeFormatter, copy+paste the TextFormatter code and make your changes there. Logrus accepts setting custom formatters.
Consider spending a bit of time using a middleware in your server. At the beginning of the request you set a context value with the log entry you have created, setting all the fields to meet your needs. This will be future-proof in case your company decides moving from files to a better logging management system.
func addLogInfo(w http.ResponseWriter, r *http.Request, next http.Handler) {
ctx := context.WithValue(req.Context(), "logEntry", log.WithFields(log.Fields{
"TraceID": r.Context.Value("trace_id"),
"IP": strings.Split(r.RemoteAddr, ":")[0],
"Body": string(reqBody[:]),
UserAgent": r.UserAgent(),
}))
req = req.WithContext(ctx)
next.ServeHTTP(w, req)
}
You can retrieve it later on:
log := req.Context().Value("logEntry")
log.WithFields("morefields").Info("Message containing all the request data")
3.- Create a pull request to be able to disable quoting (is enabled by default to be backwards compatible) so the developer, accepting full responsibility :) disables quoting in the formatter.
The quoting here is required so that the log message values can be recovered later without conflicting with the text log format.
If you need something different, you should be able to make a custom formatter.
You could also make a function that takes a json string and returns a logrus.Fields object:
fields := jsonToFields(jsonString)
logrus.WithFields(fields).Info("json fields are on this msg")
I aggree with @Wang-Kai , backslash is so ugly in log file . may there a option to disable this?
backslash harms read experience, and it is hard to copy to json web format application
3.- Create a pull request to be able to disable quoting (is enabled by default to be backwards compatible) so the developer, accepting full responsibility :) disables quoting in the formatter.
This seems like the easiest thing to do.
Any update?
Any update?
The option DisableQuote of text_formatter solve to me.
https://godoc.org/github.com/sirupsen/logrus#TextFormatter
Most helpful comment
I think it is useful in some case .
For example , i want to log every request , fields including trace_id 銆乮p銆乁serAgent銆乺equest body and so on . So the perfect log like :
It is comfortable to check every request log. The code maybe like that :
My request body is JSON like data, so if double quotes prefix with backslash is so ugly in log file . Your solution is so smart, but it only can translate JSON data to map[string]interface{} , maybe it can't meet my needs .