Query Monitor 3.0 quietly introduced a feature which allows developers to profile the running time and memory usage of their code. Query Monitor 3.1 adds a PSR-3 compatible logger which allows developers to log debugging messages to Query Monitor.
Let’s take a look at profiling and logging in detail.
Profiling
Basic profiling can be performed and displayed in the Timings panel in Query Monitor using actions in your code:
// Start the 'foo' timer:
do_action( 'qm/start', 'foo' );
// Run some code
my_potentially_slow_function();
// Stop the 'foo' timer:
do_action( 'qm/stop', 'foo' );
The time taken and approximate memory usage used between the qm/start
and qm/stop
actions for the given function name will be recorded and shown in the Timings panel. Timers can be nested, although be aware that this reduces the accuracy of the memory usage calculations.
Timers can also make use of laps with the qm/lap
action:
// Start the 'bar' timer:
do_action( 'qm/start', 'bar' );
// Iterate over some data:
foreach ( range( 1, 10 ) as $i ) {
my_potentially_slow_function( $i );
do_action( 'qm/lap', 'bar' );
}
// Stop the 'bar' timer:
do_action( 'qm/stop', 'bar' );
Here’s what the Timing panel looks like:

Note that the times and memory usage displayed in the Timings panel should be treated as approximations, because they are recorded at the PHP level and can be skewed by your environment and by other code. If you require highly accurate timings, you’ll need to use a low level profiling tool such as XHProf.
Logging
Debugging messages can be sent to the Logs panel in Query Monitor using actions in your code:
do_action( 'qm/debug', 'This happened!' );
You can use any of the following actions which correspond to PSR-3 and syslog log levels:
qm/emergency
qm/alert
qm/critical
qm/error
qm/warning
qm/notice
qm/info
qm/debug
A log level of warning
or higher will trigger a notification in Query Monitor’s admin toolbar.
Here’s what the Logs panel looks like:

Contextual interpolation can be used via the curly brace syntax:
do_action( 'qm/warning', 'Unexpected value of {foo} encountered', [
'foo' => $foo,
] );
A WP_Error
or Exception
object can be passed directly into the logger:
if ( is_wp_error( $response ) ) {
do_action( 'qm/error', $response );
}
try {
// your code
} catch ( Exception $e ) {
do_action( 'qm/error', $e );
}
Finally, the static logging methods on the QM
class can be used instead of calling do_action()
:
QM::error( 'Everything is broken' );
I hope you find these two new features useful. As always, feature requests and bug reports can be reported on Query Monitor’s GitHub repo.
Fantastic, thanks!
Curly braces are great for simple variable but not so much for objects, even with a print_r.
Currently I trigger 2 actions: message first, then the object. This way I get a since printed version of the context.
What would be the best way to pass an array or object as context for qm/debug?
Thanks.
I’ve been thinking of ways to improve this too. I might introduce another set of actions for logging a message along with more data. We’ll see.
I look forward to it 🙂
it would be an awesome feature for Query monitor to be able to enable WP_DEBUG and logging from an admin page and see the errors there. Sometimes when there’s a fatal php error on a front end page, the admin bar doesn’t show at all, hence the debug bar is not accessible either to see what is causing the error. With an admin page that lists the debug log entries this would be easy to circumvent.
Thanks for the suggestion. QM tries hard to show fatals when they occur but it’s not always possible. A screen to view the logs sounds like a good idea.