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
$_POSTdata, 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