php, error_log and newlines: a solution

15th May, 2012 - Posted by david

When it comes to coding and debugging, I generally keep things simple, opting for a basic text editor (Sublime Text 2 with Vim key-bindings being my current choice) and simple debug output statements when trying to track down a bug. With my current job, I deal with an API over AJAX so it’s not easy to send debug statements to the browser, hence had been using a combination of PHP’s error_log and print_r($var, 1) to get the value of a variable on the server. When debugging this way, I’d usually be doing a tail -f on my error log file, monitoring changes to that as I go.

This was all fine, but got very frustrating when dealing with arrays, objects and even strings with newline characters. The reason for this frustration was that newline characters were being displayed in the error log as \n and no new line, so something like

1
2
$var = array('zero' => 0, 'one' => 1);
error_log(print_r($var, 1));

would produce:

1
Array\n(\n    [zero] => 0\n    [one] => 1\n)

instead of the nicer:

1
2
3
4
5
Array
(
    [zero] => 0
    [one] => 1
)

Not too bad for small arrays but for large objects it’s a nightmare! Googling around didn’t have an easy answer. I’m sure it’s some setting deep in php.ini or my Apache config, but I managed to come up with a pretty neat solution, which I’m going to document here.

I started by creating my own error log in /tmp/derror (David’s Error = derror!) and letting any one write to it (I realise this could be slightly cleaner/more secure):

1
2
touch /tmp/derror
chmod 766 /tmp/derror

Next I needed a nice debug function to write to this file. I wrote one that’ll take any number of parameters and for each one, output the current time along side a dump of their value. If it’s an object or class, use print_r, otherwise just display the value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function derror() {
  $f = fopen('/tmp/derror', 'a');
  foreach (func_get_args() as $obj) {
    fwrite($f, date('Y-m-d G:i:s')."\n");
    if (is_array($obj) || is_object($obj)) {
      fwrite($f, print_r($obj,1)."\n\n");
    }
    else {
      fwrite($f, $obj."\n\n");
    }
  }
  fclose($f);
}

// called like
derror($var1, $var2);

So, that function works fine but after a while I realised by doing my tail -f on my new error file, I was missing out on the real server errors. So, I had 2 different terminal tabs open, flipping between them both, which got annoying after about 2 errors! Luckily, I quickly thought of a way around this: route PHP’s error logging to my new file. The way Apache and virtual hosts are set-up this was quite easy and you can even log to 2 different files, thus preserving your ‘normal’ error file too. so, in your /etc/apache/sites-available/default or whatever, in the <Virtualhost:*.80> block for your site, copy the line for CustomLog and point that to your error file, i.e.

1
CustomLog /tmp/derror combined

This should now route all Apache errors to your new file, so you have the best of both worlds!

To prevent the file getting to big over time, I set-up a cron job to simply delete the file and create a new one every Monday morning.

Tags: php | david | 15th May, 2012 at 19:21pm | No Comments

No Comments

Leave a reply

You must be logged in to post a comment.