Debugging

If WordPress data seems out of date, or should the “White Screen of Death” ever occur, the first action is always to flush the cache. You can do that easily with the wp cache flush CLI command or through the dashboard widget.

Bypassing the cache

If the flushing the cache doesn’t resolve the issue you’re experiencing; you can quickly disable the entire object cache.

Simply delete the wp-content/object-cache.php drop-in file in, or set the WP_REDIS_DISABLED environment variable to any non-empty value, such as 1 or yes.

Alternatively, use the WP_REDIS_DISABLED kill switch constant in you wp-config.php:

define('WP_REDIS_DISABLED', true);

Debugging with Query Monitor

Object Cache Pro integrates tightly with the Query Monitor plugin. Make sure the plugin is installed, activated, and you’re logged into WordPress. To open it up, click on the Query Monitor node in your admin bar.

You’ll see cache hits, misses, and everything you need to know about the current request, as well as details about cache groups and diagnostics.

Additionally, if WP_DEBUG or SAVEQUERIES is enabled, you’ll see all executed Redis commands and who triggered them.

See Diagnostics for more information.

Debugging with Loggers

Debugging cache issues is a breeze using the logging module.

Sometimes finding the issue is as easy as opening up Query Monitor and looking at what’s going on for that request, but often it’s not.

Let’s walk through a real-world scenario.

Acme Corp. was using Redis Object Cache, but sometimes getting shipping rates for international packages would not work. They managed to narrow it down to an empty array being stored in Redis when it should have been shipping rates, however sometimes, an empty array was the correct value since shipping to that country wasn’t supported.

Now the task was finding out who the culprit was since several shipping plugins could have caused it.

They set up Object Cache Pro and a custom logger to reduce the number of log entries, since they had millions of Redis operations each hour, and a horizontally scaled infrastructure with a dozen web servers.

class AcmeShippingLogger extends \RedisCachePro\Loggers\Logger
{
    public function log($level, $message, array $context = [])
    {
        // only log commands starting with `SET`, like `SETEX` and similar
        if (stripos($context['command'], 'set') === 0) {
            return;
        }

        // only log commands for keys called `shipping-rates`
        if (stripos($context['parameters'][0], ':shipping-rates') === false) {
            return;
        }

        // lookup and store who’s called the command as context
        $context['backtrace'] = \wp_debug_backtrace_summary(__CLASS__);

        // store the log entry in memory
        $this->messages[] = [
            'level' => $level,
            'message' => $message,
            'context' => $context,
        ];
    }

    // store all messages at once in logging instance,
    // including log level, message, context and backtrace
    public function __destruct()
    {
        if (empty($this->messages)) {
            return;
        }

        try {
            $redis = new \Redis;
            $redis->connect('127.0.0.5', 6379);
            $redis->rPush('objectcache:logs', ...array_map('json_encode', $this->messages));
        } catch (\Exception $e) {
            //
        }
    }
}