Daniele Scasciafratte

The bad, the ugly and Query Monitor

The right way to debug in WordPress

Daniele Scasciafratte / @Mte90Net

Daniele Scasciafratte

  • Co Founder/CTO Codeat
  • Italian Linux Society council member
  • Mozillian
  • WordPress Core Contributor/Developer
  • Podcast 🇮🇹 Daniele.tech - Opinioni in open source
  • Old school developer

Choose one

Remember in this world there are two kinds of people, my friend: Those with tools and those who have only errors.
You have only errors.

Art of debugging

“While the meaning of the verb to debug is to remove errors, in reality it is more about seeing step by step execution of a program. As well as examining it against some specification of how program should behave. A programmer who has no access to high quality debugger is like a shortsighted person. He can function but he can miss some dangerous things in the environment very easily. ”

Joe's (Joe Armstrong) Law of Debugging

“All errors will be plus/minus three statements of the place you last changed the program”

First of all

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', true );
define( 'SCRIPT_DEBUG', true );
# If you need Jetpack
define( 'JETPACK_DEV_DEBUG', true );
define( 'JETPACK_STAGING_MODE', true );
# If you need Freemius
define( 'WP_FS__SKIP_EMAIL_ACTIVATION', true);
define( 'WP_FS__DEV_MODE', true );

3 phases of debugging

DOH

3 phases of debugging

Understand the taste

3 phases of debugging

Release the hot patch

The real 3 phases

  • Replicate the bug
  • Isolate and understand the bug
  • Do the magic killer patch

In this talk we will focus on phase 2

User (classic) case

  • User open a form: "Riscuotere la taglia"
  • User input some data: "Nome: El gringo"
  • User get output: "Taglia incassata, 200 Wapuu $"
  • Data should be sanitized: "Non si lava da mesi"
  • Data should be parsed: "Scappato con un buco nel muro"

Let's inspect the data

The Bad way

echo $var;
print_r( $var );
var_dump( $var );
var_dump( $var ); die();

The ugly way

Custom Error log path in WP 5.2

define( 'WP_DEBUG_LOG', 'path/to/log/file' );

Print what you want in the log of your web server

error_log( print_r( $var, true ) );

The ugly old school way

function vvv-debug(){
    log="/var/www/VVV/www/$1/htdocs/wp-content/debug.log"
    if [ ! -f $log ]; then
        log="/var/www/VVV/www/$1/public_html/wp-content/debug.log"
    fi
    
    if [ -f $log ]; then
        actualsize=$(du -k $log | cut -f 1)
        if [ $actualsize -ge 300 ]; then
            rm $log;
        fi
        echo "" > $log
        multitail -cS php -m 600 $log;
    else
        echo "Log not found"
    fi
}
# Open the log in a terminal of a specific site in VVV
$ vvv-debug demo

The ugly old school way

(
    [error] => Notice
    [file] => /home/domain/wp-content/plugins/lifterlms/vendor/ericmann/wp-session-manager/includes/class-wp-session.php
    [line] => 77
    [context] => Array
        (
            [cookie] => cxxxxxxxxxxx
            [cookie_crumbs] => Array
                (
                    [0] => cxxxxxxxxxxx
                )

        )

    [url] => https://domain/author/daniele/feed/
    [filter] => plugins_loaded
    [path] => /home/domain/wp-content/plugins/lifterlms/vendor/ericmann/wp-session-manager/includes/class-wp-session.php
    [message] => Notice (8): Undefined offset: 1 in [/home/domain/wp-content/plugins/lifterlms/vendor/ericmann/wp-session-manager/includes/class-wp-session.php, line 77]
)

Drop-in mu-plugin by Me (Query monitor supported).

The Query Monitor way

The spaghetti western way of Blow your mind.

In your wp-config.php

define( 'QM_HIDE_SELF', true );
define( 'QM_HIDE_CORE_HOOKS', true );

Integrate in your plugin

Create a custom alternative panel for log stuff inside Query Monitor
Add a timer method that use the Query Monitor internals
Add a method to print in the internal log panel of Query Monitor
$debug = new WPBP_Debug( __( 'Name of the panel', 'your-textdomain' ) );
$debug->log( __( 'Plugin Loaded', 'your-textdomain' ) );
$debug->qm_log( __( 'Error inside the log panel of Query Monitor', 'your-textdomain' ), 'error' );
$debug->qm_timer( 'profile_that_callback', function () { echo 'I need to be profiled!'; } );

https://github.com/WPBP/Debug

Companions

xDebug





WP-CLI Profile command

wp profile stage --all
+--------------------------+----------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
| hook                     | callback_count | time    | query_time | query_count | cache_ratio | cache_hits | cache_misses | request_time | request_count |
+--------------------------+----------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+      |
| plugins_loaded:before    |                | 0.2855s | 0.0041s    | 19          | 83.95%      | 136        | 26           | 0s           | 0             |
| plugins_loaded           | 34             | 0.2442s | 0.0009s    | 3           | 98.31%      | 116        | 2            | 0s           | 0             |
| setup_theme:before       |                | 0.0005s | 0s         | 0           | 100%        | 4          | 0            | 0s           | 0             |
| setup_theme              | 1              | 0s      | 0s         | 0           |             | 0          | 0            | 0s           | 0             |
+--------------------------+----------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
| total (31)               | 242            | 1.4571s | 0.0284s    | 78          | 90.8%       | 3323       | 84           | 0s           | 0             |
+--------------------------+----------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
wp profile hook --all --spotlight --url=https://yourdomain.com
+----------------------------------------------+-----------------------------------------------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
| callback                                     | location                                            | time    | query_time | query_count | cache_ratio | cache_hits | cache_misses | request_time | request_count |
+----------------------------------------------+-----------------------------------------------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
| wpseo_init()                                 | wordpress-seo/wp-seo-main.php:252                   | 0.0136s | 0s         | 0           | 100%        | 34         | 0            | 0s           | 0             |
| wp_enqueue_scripts()                         | wp-includes/script-loader.php:1294                  | 0.015s  | 0s         | 0           | 100%        | 348        | 0            | 0s           | 0             |
| wp_trim_excerpt()                            | wp-includes/formatting.php:3289                     | 0.0186s | 0s         | 0           | 100%        | 16         | 0            | 0s           | 0             |
+----------------------------------------------+-----------------------------------------------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
| total (7)                                    |                                                     | 0.0927s | 0.0006s    | 6           | 100%        | 1054       | 0            | 0s           | 0             |
+----------------------------------------------+-----------------------------------------------------+---------+------------+-------------+-------------+------------+--------------+--------------+---------------+

WP Query Console