How to log pretty printed json in PHP?
Asked Answered
C

3

8

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?

Chattel answered 13/7, 2015 at 14:34 Comment(8)
you need to add \n into your JSON... so, you need to parse your JSON after encoding to add \n after what you want.. so after "," and "}" and before } when "," not appear after.Myrtlemyrvyn
#352598Wineskin
dude, first decode the json stringAstronomical
@MarcB Not PHP relatedChattel
@KarolyHorvath Can you provide some code please?Chattel
@Jean-philippeEmond Can you post an answer explaining your point please?Chattel
@Stephan: you must be kidding...Astronomical
Use your own error handler instead of forcing the native one into a format which it is not supposed to. Btw, read the warning boxes on php.net/error_logShanks
T
21
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.

Tirado answered 13/7, 2015 at 16:31 Comment(3)
What's the difference between JSON and "something that can be read by javascript"-from-a-function-called-json_encode ? lol :D The answer is inaccurate in my opinion. No offence.Shanks
@DanFromGermany. "Like the reference JSON encoder, json_encode() will generate JSON that is a simple value (that is, neither an object nor an array) if given a string, integer, float or boolean as an input value. While most decoders will accept these values as valid JSON, some may not, as the specification is ambiguous on this point." json_encode()Tirado
My wording could perhaps be clarified. I'd say that the "simple value" output is not true JSON, but it seems that there's debate on that point.Tirado
S
1

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.

Shanks answered 13/7, 2015 at 16:40 Comment(0)
M
0

You have two options in this case,

if you can use a str_replace like:

error_log("test\n" . str_replace('\"',"\n",json_encode($json_string, JSON_PRETTY_PRINT)));

or like @Karoly Horvath said:

You encode a string already encoded in a JSON. Your $json_string is already encoded. So you need to decode your first JSON and re-encode it with good parameters

error_log("test\n" . json_encode(json_decode($json_string), JSON_PRETTY_PRINT));

and give credit to @Karoly.

Myrtlemyrvyn answered 13/7, 2015 at 16:19 Comment(2)
Why replace escaped quotation marks by newlines?? Btw, you should use the constant PHP_EOL instead of \n or \r\n, etc.Shanks
Good point. its not the best answer. its just to explain a working code. the best answer is @Karoly Horvath. I did'nt see that is both json encoding. but I don't want to stole answer of people so, I explain mine like I said on the comment. ;-). For the PHP_EOL, I just forget this global.Myrtlemyrvyn

© 2022 - 2024 — McMap. All rights reserved.