← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Error Logging

php PHP 4.0+ Beginner
debt(d7/e5/b7/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints.tools field is empty, so no specialist tool is cited from metadata. Missing or misconfigured error logging (e.g. display_errors=On in production, no log aggregation, no alerting) is not caught by the compiler, linter, or a standard SAST scan — it only becomes apparent when reviewing configuration files carefully or when a production incident reveals that no logs were captured. Slightly better than d9 because a code review of php.ini or bootstrap config will surface it.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix mentions setting error_reporting(E_ALL), log_errors=On, display_errors=Off, and adding Monolog with a file handler plus Sentry. This is more than a one-liner: it involves php.ini or runtime config changes, installing and wiring a logging library (Monolog), setting up Sentry integration, adding contextual data to existing log calls across the codebase, and configuring log rotation and alerting. That spans multiple files and components, landing squarely at e5.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Error logging applies to both web and CLI contexts (applies_to: web, cli) and is a cross-cutting concern in any PHP application. Every component that handles errors, exceptions, or warnings must integrate with the chosen logging strategy. The choice of logging library (Monolog/PSR-3), log destination, and aggregation service shapes how every future feature is instrumented. Poorly set up logging silently degrades over time (file bloat, no alerting) affecting all work streams — a persistent, wide-reaching structural burden.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly states: 'Logging errors means they are visible and actionable.' A competent developer naturally assumes that writing to a log file constitutes effective error management. The trap is that file-based logs accumulate unread, no alerting fires, errors go unnoticed for days, and the developer believes the system is monitored when it is not. This contradicts the intuitive expectation that 'I set up logging, therefore I will know about errors' — a serious, well-documented gotcha that most developers only learn after a painful production incident.

About DEBT scoring →

Also Known As

logging Monolog PSR-3 error_log application logging Sentry log levels

TL;DR

Recording application errors, exceptions, and diagnostic information to persistent storage — essential for diagnosing production issues where display_errors must be off and errors are invisible to users.

Explanation

PHP error logging has two layers: PHP's built-in error logging (configured via error_log in php.ini or error_log() function) and application-level logging (PSR-3 compatible libraries like Monolog, used by Laravel and Symfony). PHP logs errors to the file specified by error_log directive, or to the web server error log. Monolog supports structured logging with context arrays, multiple output handlers (file, Slack, email, Elasticsearch), and log levels following RFC 5424 (DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY). Production configuration: error_reporting(E_ALL), log_errors=On, display_errors=Off, log_errors_max_len=0. For exceptions: use a global exception handler (set_exception_handler()) or middleware to log uncaught exceptions before showing a generic error page. Error aggregation services (Sentry, Bugsnag, Flare) group duplicate errors, track frequency, and alert on new error types.

Common Misconception

Logging errors means they are visible and actionable. Logging is only useful if someone reads the logs. File-based logs on a busy server accumulate gigabytes and nobody reads them. Effective error management requires: log rotation (logrotate), centralised aggregation (a service that collects logs from all servers), alerting on new error types, and error grouping so you see '500 occurrences of DB connection failed' not 500 separate log lines. Log the error, then also set up alerting.

Why It Matters

In production, display_errors must be off — showing raw PHP errors to users exposes file paths, database credentials, and stack traces that attackers use for reconnaissance. With display_errors off, the only way to diagnose production errors is through logs. A PHP application with no error logging is flying blind — customer-reported bugs have no diagnostic trail, errors discovered by users may have been occurring for days or weeks, and silent exceptions cause data corruption that only surfaces much later.

Common Mistakes

  • Setting display_errors=On in production — exposes sensitive error details to end users and attackers.
  • Not setting error_reporting(E_ALL) — missing E_NOTICE and E_DEPRECATED hides warnings about deprecated features that break on upgrade.
  • Not including context in log messages — log('Payment failed') is useless; log('Payment failed', ['user_id' => $id, 'amount' => $amount, 'gateway_response' => $response]) is actionable.
  • Logging sensitive data — never log passwords, full credit card numbers, or session tokens; log IDs and non-sensitive identifiers instead.
  • Logging to stdout in CLI scripts without timestamps — makes post-mortem impossible; always prefix every line with a machine-parseable timestamp.

Code Examples

✗ Vulnerable
// display_errors=On in production — leaks internals
// No structured logging — useless for diagnosis
try {
    $payment->charge($amount);
} catch (Exception $e) {
    error_log($e->getMessage()); // no context
    echo 'Error: ' . $e->getMessage(); // shown to user!!
}
✓ Fixed
// Structured logging with context
try {
    $payment->charge($amount);
} catch (PaymentException $e) {
    $this->logger->error('Payment charge failed', [
        'user_id'          => $user->id,
        'amount'           => $amount,
        'gateway'          => $payment->gateway(),
        'gateway_code'     => $e->getCode(),
        'exception'        => $e->getMessage(),
    ]);
    // Show generic message to user
    throw new UserFacingException('Payment could not be processed.');
}

Added 23 Mar 2026
Edited 18 Apr 2026
Views 27
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 8 Perplexity 7 ChatGPT 1 Majestic 1 Google 1 Ahrefs 1
crawler 19
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Set error_reporting(E_ALL), log_errors=On, display_errors=Off in production. Use Monolog with a file handler minimum; add Sentry for error aggregation and alerting
📦 Applies To
PHP 4.0+ web cli
🔗 Prerequisites

✓ schema.org compliant