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.