WordPress Error Logging That Doesn’t Suck

A client with a high-traffic WooCommerce shop called me up. They were getting hammered with support tickets about an intermittent “invalid coupon code” error at checkout. Some customers saw it, some didn’t. Total mess. I checked the logs, and of course, they were useless. The standard PHP error log had nothing, and the WooCommerce logs just had a generic “coupon invalid” line with no context. When you can’t reproduce a bug, you can’t fix it. This is where having a sane WordPress error logging strategy isn’t just nice—it’s essential.

My first, gut reaction was to litter the coupon processing functions with error_log(print_r($some_variable, true)). And yeah, it dumped a ton of data into the debug.log. But it was a firehose of noise. A massive, unsearchable text file that didn’t even tell me who the user was, what else was in their cart, or what their session data looked like. It was a classic rookie mistake, and it just made the problem worse. The real issue is that an error message without context is just noise.

Beyond Basic Logging: Capturing Actionable Context

The core of the problem isn’t just knowing an error happened; it’s understanding the *state* of the application when it broke. This builds on a concept I saw outlined over at carlalexander.ca about designing for error management. You have to think about what a developer actually needs to do their job. For me, it breaks down into two key jobs: triaging the error (how bad is it?) and debugging the error (what caused it?).

  • For Triage: You need a quick summary. What was the error message? How many times has it happened? When was the first and last time? Is it tied to a specific user role?
  • For Debugging: This is where you need the heavy-duty data. The full stack trace, the URL and request method, the full $_POST data, relevant session data, and in a WooCommerce context, the user’s cart contents.

Instead of just dumping raw text, the solution is structured logging. We capture all that rich context and log it as a clean, predictable JSON object. It’s searchable, parsable, and gives you a complete snapshot of the failure.

function custom_contextual_error_log($message, $data = []) {
    $log_entry = [
        'timestamp' => current_time('mysql'),
        'message'   => $message,
        'request'   => [
            'method' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'N/A',
            'uri'    => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'N/A',
            'post'   => $_POST,
        ],
        'user'      => [
            'id'   => get_current_user_id(),
            'role' => is_user_logged_in() ? wp_get_current_user()->roles[0] : 'guest',
        ],
        'context'   => $data, // e.g., WC()->cart->get_cart_contents()
    ];

    // Use error_log to write the JSON string to your debug.log
    // In a real-world scenario, you might send this to a dedicated logging service API
    error_log(wp_json_encode($log_entry));
}

// Example usage in WooCommerce
// add_action('woocommerce_coupon_error', 'log_coupon_errors', 10, 2);
// function log_coupon_errors($err_code, $coupon) {
//     custom_contextual_error_log(
//         'WooCommerce Coupon Error: ' . $err_code,
//         [
//             'coupon_code' => $coupon->get_code(),
//             'cart_total'  => WC()->cart->get_cart_total(),
//             'cart_items'  => WC()->cart->get_cart_contents_count(),
//         ]
//     );
// }

So, What’s the Point?

Here’s the kicker: You don’t need a fancy, expensive logging service to do this right, though they can help. The point is to be intentional. Stop thinking of logging as just printing a message and start thinking of it as serializing the state of your application when things go south. Capturing the user, the request, and the application-specific context is the only way to make debugging efficient and save yourself from a total nightmare of guesswork.

Look, this stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.

Leave a Reply

Your email address will not be published. Required fields are marked *