PHP error reporting and logging

Logging and error reporting are parts of a debugging process. For some programmers, putting

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('SAVEQUERIES', true);
define('SCRIPT_DEBUG', true);

in the wp-config.php file is the end of the story. Let’s discuss how we can improve the debugging process of our WordPress-based web app.

As you probably know, enabling WP_DEBUG forces the application to collect and report all levels of errors. Making WP_DEBUG_LOG true also records these errors into wp-content/debug.log file. Errors get logged and reported, nice.
But what if we want to log our own error messages? Or better yet, display contents of a variable on a web page?

I’ve seen people (myself included) use variations of PHP’s classical outputting functions:

echo "my message";
print_r($my_array);
var_dump($my_array);
var_export($my_array);

var_dump the variable, see what’s inside, remove the var_dump and continue, right?

No. Why?

A while later, I need to see the contents of the same variable again so I have to write yet another var_dump and then remove it. But wouldn’t it be better if I didn’t have to remove and add these functions? What about logging the variables and displaying the logs conditionally and in a controlled manner? Only if WP_DEBUG is enabled, for example.

Custom logging function

Some developers came with a simple solution: write a custom logging function for reporting your own messages.

function log_me($message) {
    if (WP_DEBUG === true) { // log messages only when debugging is enabled
        if (is_array($message) || is_object($message)) {
            error_log(print_r($message, true));
        } else {
            error_log($message);
        }
    }
}

Then, you would just write log_me('my super important message') somewhere in your code and your message would be then recorded in the debug.log file.

I don’t like this solution. Reasons why:

  • Cannot specify error level. What if I just want the message to be of E_USER_NOTICE level?
  • Have to include this custom function in all your WordPress projects.

trigger_error to the rescue

PHP has a secret function called trigger_error. It fires an error of specified type (level) with a custom message. The default type is E_USER_NOTICE, which is suitable for logging contents of a variable or custom messages.

add_action( 'init', 'lamosty_init' );

function lamosty_init() {
        // log a simple message
    trigger_error( 'in init action hook' );
}

add_action( 'pre_get_posts', 'lamosty_pre_posts' );

function lamosty_pre_posts( WP_Query $query ) {
        // log the actual WP_Query
        // we use var_export for output to be nicer
    trigger_error( var_export( $query, true ) );
}

Open wp-content/debug.log and see for yourself. The message and $query are recorded in the file.

Now, if we disable debugging in our WordPress site

define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);

no errors are logged or displayed anywhere! We don’t have to remove the calls to trigger_error even when moving the site to production (live) server. Want to see the messages or contents of variables? Just enable debugging in WordPress.

Setting error reporting levels

WordPress logs all levels of errors by default. However, I want only E_USER_WARNING error types be reported in my functions.php file. Since I used trigger_error for my custom logging purposes, it’s no brainer. Just put

error_reporting(E_USER_WARNING & ~E_USER_NOTICE);

at the top of the file.

Configuring custom error handling function

What is more, we can also have our own error handling function. As an example, let’s say that I want to print all logged messages into browser’s JavaScript console so I don’t have to look into debug.log. Open up your functions.php file and add

$lamosty_errors = array();

function lamosty_error_handler( $errno, $errstr, $errfile, $errline, $errcontext ) {
    global $lamosty_errors;

        // store all error messages in a global array
    array_push( $lamosty_errors, $errstr );

}

// configure the function 'lamosty_error_handler' to be the default error handling function
set_error_handler( 'lamosty_error_handler' );

before all of your trigger_error calls. After that, we hook into the shutdown action and print all the collected messages:

add_action( 'shutdown', 'lamosty_print_errors_in_js' );

function lamosty_print_errors_in_js() {
    global $lamosty_errors;

    ?>

    

        

                console.log("");

                

    

<?php

}

Reload your WordPress site and inspect the browser’s console. All triggered messages and errors are present there. Pretty neat, isn’t it?

Conclusion

I hope I’ve convinced you that using trigger_error function better than logging the errors directly because you have a much greater control of what and how things get logged. Even better than logging the output of function calls or variables is to write Unit Tests but I’ll leave that for another day.

Don’t forget to install Query Monitor plugin. It has its own error handling routines displaying the messages in a nice UI.

Figure 1: Query Monitor  showing logged messages
Figure 1: Query Monitor showing logged messages

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: