I'm building an API in php. This API processes json messages from a third party API.
I want to log invalid pretty printed json messages.
So I did this:
error_log("test\n" . json_encode($json_string, JSON_PRETTY_PRINT));
However, when I look at my logs, the json string is not pretty printed:
$ tailf error.log
2015-07-13 10:20:03: (mod_fastcgi.c.2701) FastCGI-stderr: test
"{\"info\":{\"status\":200,\"msg\":\"OK\"},\"response\":{\"foo\":\"bar\"}"
I want to see something like:
$ tailf error.log
2015-07-13 10:20:03: (mod_fastcgi.c.2701) FastCGI-stderr: test
{
"info": {
"status": 200,
"msg ": "OK"
},
"response": {
"foo": "bar"
}
}
How can I achive this result?
error_log("test\n" . json_encode($json_string, JSON_PRETTY_PRINT));
json_encode()
will actually not necessarily produce JSON: it will produce something that can be read by javascript. If you give it an array or an object, it will produce JSON; if you give it a string, it will produce a javascript string. And that’s what you’re doing, so that’s what you’re getting.
To be clear, $json_string
is a string: (as far as PHP is concerned, it’s a string; if you passed that same string to javascript, it would be interpreted as an object). You pass that through json_encode()
and all you’re going to get is another string (a string of doubly-encoded JSON).
JSON_PRETTY_PRINT
is having no effect here, because you’re not producing JSON: you’re producing something that javascript too would see as a string.
Savvy?
So what you need to do is to (a) turn $json_string
back into a PHP array, and then (b) reencode that as JSON, this time using the JSON_PRETTY_PRINT
flag.
$log_array = json_decode($json_string, true);
$json_pretty_string = json_encode($log_array, JSON_PRETTY_PRINT);
error_log('test' . PHP_EOL . $json_pretty_string);
Rather than converting it back to a PHP array and then back to JSON, it would be better to add the JSON_PRETTY_PRINT
flag to wherever you’re getting $json_string
from in the first place, if possible.
Alternatively, just log $json_string
directly (no need to encode it: it’s already a string, you can pass it to error_log()
as it is), and worry about prettifying it only when you need to read your logs. This will make your logs considerably smaller.
Common unix error logs are not supposed to contain human-readable json or other unescaped characters. Many syslog/logging implementations are limited by character width and automatically add encoding (like \"
) or remove new line characters, PHP's error_log is not binary safe either - the behaviour when encountering a unicode character is unpredictable tho (not sure).
You should not be using the native syslog/error log functions, instead, build your own logger, dedicated to json logging.
Personally I use MongoDB for logging json, because it's the kind of data MongoDB is supposed to work with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With