Logging in WordPress and WP-CLI
In this lesson you will enable the PHP error log for WP-CLI runs, update your cron configuration to log all scheduled tasks, create a WP-CLI command log for audit, and secure your debug.log from external access.
Logging plays such a big role in diagnosing problems with your WordPress site, and it can be extremely frustrating when you're unable to quickly find the logs you're looking for, especially when they don't exist.
So far we have Nginx access and error logs, as well as the PHP pool error and
slow logs configured in our per-site logs directory. However, our per-site PHP
configuration is only for the PHP-FPM pool, meaning it's only applied to HTTP
traffic.
WP-CLI error logs
Our CLI configuration is still a global one, and that's the configuration used
for any WP-CLI commands too. Any errors, including ones occurring in WP-Cron
runs, will only be output to the current stderr without being logged anywhere.
We can address this by creating a per-site configuration for PHP CLI.
Unfortunately, there is no built-in per-directory php.ini support in PHP.
However, we can overcome this by using WP-CLI's require configuration, and
address the problem with some PHP code.
First, let's create our new PHP script which we'll include with every run of
WP-CLI. I'll place mine in /config/misc/wp-cli-logging.php:
<?php
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
return;
}
\WP_CLI::add_hook( 'before_wp_load', function() {
ini_set( 'log_errors', '1' );
ini_set( 'error_log', dirname( ABSPATH ) . '/logs/php-errors.log' );
} );
Here we ensure that we're running in a WP_CLI context, then use the WP-CLI
hooks system to run a function on its before_wp_load event, which is very
early in the bootstrap process but late enough that the target WordPress
configuration file has been read, and the ABSPATH constant has been defined.
We use this to set the error_log path to the same php-errors.log file where
our PHP-FPM pool configuration is set to log errors.
Next we'll need to update our WP-CLI YAML configuration, to make sure this new
file is loaded every time the CLI is invoked. This can be done in our existing
/config/misc/wp-cli.yml file, which now looks like this:
disabled_commands:
- db drop
- db reset
- site empty
require:
- /config/misc/wp-cli-logging.php
Now, triggering an error in a WP-CLI command will lead to that error being
logged to our corresponding php-errors.log file. You can test this by
intentionally causing a fatal error, and watching the log file:
cd /sites/uncached.org/public_html
wp eval "undefined();"
tail -n20 ../logs/php-errors.log
Note that errors happening without a proper WordPress context will still only be shown on screen. Cron runs, however, occur in a valid WordPress context, so any errors during a background task will be logged to the correct file.
WordPress Cron logs
In addition to logging PHP errors, I highly recommend logging the WordPress cron in general. That way you'll always have a reference of what ran when and why, even if it didn't produce any errors.
I recommend using the ts utility for this, which adds timestamps to output.
This is part of the moreutils package in Ubuntu and other Debian-based
distributions:
sudo apt install moreutils
echo hello | ts
Let's now update our system cron configuration file, and have the WP-Cron runner
output the results to a log file with timestamps. My system cron configuration
is in /config/misc/crontab:
* * * * * www-data flock -n /sites/uncached.org/wp-cron.lock wp --path=/sites/uncached.org/public_html cron event run --due-now 2>&1 | ts >> /sites/uncached.org/logs/cron.log
As mentioned in an earlier lesson, this has to be a one-liner, but here is the command that runs, split into multiple lines for readability:
flock -n /sites/uncached.org/wp-cron.lock \
wp --path=/sites/uncached.org/public_html \
cron event run --due-now 2>&1 \
| ts >> /sites/uncached.org/logs/cron.log
We use the same locking technique as before, however this time we redirect
stderr to stdout using 2>&1, pipe the output to the timestamp utility
ts, and finally append it to the relevant cron.log file.
Check your cron.log file in a few minutes to make sure it's being written to.
Since we are redirecting stderr to stdout, any PHP errors during that run
will also be written to this log file, in addition to the site's
php-errors.log.
WordPress debug.log
WordPress has a WP_DEBUG_LOG constant to turn on debug logging, and by default
it will attempt to set the log location to wp-content/debug.log. With our
existing setup this is not possible because we are using a php_admin_value
directive in our PHP pool configuration. This directive sets a configuration
value and prevents anything (including WP_DEBUG_LOG) from overriding it.
This article is for premium members only. One-time payment of $96 unlocks lifetime access to all existing and future content on wpshell.com, and many other perks.
