Back to Blog
Lesson 38 of the Advanced WordPress Plugin Engineering: Scale, Security & React UIs course
WordPressJune 28, 20263 min read

Performance Monitoring: Tracking Metrics and Errors in WordPress

Master performance monitoring in WordPress. Learn to log execution times, profile database queries, and implement robust error tracking for production stability.

WordPressPerformanceDebuggingPHPMonitoringplugin-development

Previously in this course, we covered Plugin Lifecycle Management, ensuring your database migrations and cleanup routines are robust. Now, we shift our focus from maintenance to visibility: how do you know if your plugin is actually fast in the wild?

In a professional environment, "it works on my machine" is a dangerous assumption. Performance issues often manifest only under specific database loads or high-concurrency environments. To build a truly scalable product, you must implement proactive Monitoring, Performance tracking, and Debugging hooks.

Instrumenting Code for Performance Logging

The first step in performance engineering is establishing a baseline. We need to track how long critical operations take. While Monitoring Production Performance: A Senior Engineer's Guide discusses general strategies, here we implement a lightweight timer utility within our Knowledge Base plugin.

We avoid using heavy external APMs for every minor task. Instead, we create a PerformanceLogger service that uses microtime(true) to track execution blocks.

PHP
namespace KnowledgeBase\Services;

class PerformanceLogger {
    private array $timers = [];

    public function start(string $key): void {
        $this->timers[$key] = microtime(true);
    }

    public function stop(string $key): float {
        $elapsed = microtime(true) - ($this->timers[$key] ?? microtime(true));
        #6A9955">// Log to debug.log if defined, or send to your telemetry endpoint
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log(sprintf('[KB Performance] %s: %.4f seconds', $key, $elapsed));
        }
        return $elapsed;
    }
}

Monitoring Database Query Times

Database bottlenecks are the #1 cause of slow WordPress sites. Because we've already established a Data Access Objects Pattern, we have a centralized location to inject our monitoring logic.

Rather than wrapping every query, we hook into the query filter in WordPress to capture execution time for all queries originating from our plugin's namespace.

PHP
add_filter('query', function($query) {
    if (strpos($query, 'kb_') !== false) { #6A9955">// Only track our custom tables
        $GLOBALS['kb_query_start'] = microtime(true);
    }
    return $query;
});

add_filter('query_vars', function($vars) {
    if (isset($GLOBALS['kb_query_start'])) {
        $elapsed = microtime(true) - $GLOBALS['kb_query_start'];
        if ($elapsed > 0.05) { #6A9955">// Log queries taking longer than 50ms
            error_log("Slow KB Query: $elapsed s - " . $query);
        }
    }
    return $vars;
});

Implementing Error Tracking

Performance isn't just about speed; it's about reliability. If a feature fails silently, the user experiences a "performance" issue—the site feels broken. We should catch exceptions and log them with context.

Unlike Debugging React Apps: A Professional Guide to Troubleshooting, which focuses on the client side, our server-side error tracking must be persistent.

PHP
public function safeExecute(callable $callback, string $context) {
    try {
        return $callback();
    } catch (\Throwable $e) {
        #6A9955">// Send to your error aggregation service(e.g., Sentry or custom endpoint)
        $this->errorReporter->log([
            'message' => $e->getMessage(),
            'context' => $context,
            'user'    => get_current_user_id()
        ]);
        return null;
    }
}

Hands-on Exercise

  1. Create a Timer Trait: Implement a trait that exposes startTimer() and stopTimer() methods.
  2. Instrument the Repository: Apply this trait to your Knowledge Base repository class.
  3. Threshold Logging: Modify the stopTimer() method to automatically log an error if the execution exceeds 100ms.
  4. Verification: Trigger a query that performs a JOIN on large tables and check your wp-content/debug.log to see the output.

Common Pitfalls

  • Excessive Logging: Never log every single successful request to the database. You will bloat your logs and introduce a performance penalty. Use a threshold (e.g., only log queries > 100ms).
  • Blocking Operations: Do not perform external API calls inside your performance logger. If your logging service goes down, your entire site will hang. Always use non-blocking requests (like wp_remote_post with a short timeout).
  • Namespace Collisions: Ensure your logs are prefixed (e.g., [KB-Plugin]) to distinguish them from core WordPress or other plugin logs.

Recap

We've moved beyond basic development into production observability. By instrumenting code with timers, monitoring database latency through query filters, and wrapping operations in safe execution blocks, you ensure your plugin is not just functional, but performant and debuggable in real-world environments.

Up next: Advanced Error Handling — we will build a custom error handler to gracefully manage and report fatal errors.

Similar Posts