0Pricing
PHP Academy · Lesson

Logging Errors and Best Practices

Log errors to files and follow production error-handling patterns.

Logging Errors and Best Practices is a free PHP Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the PHP Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Logging Matters

In production, you can't show errors to users but you still need to know when things go wrong. Logging captures error details to files or services so you can investigate later.

error_log()

The simplest logging function — writes a message to PHP's error log:

<?php
error_log('User login failed for: ' . $email);
error_log('DB query took: ' . $duration . 'ms');

// Send to email (not recommended for high traffic)
error_log('Critical: server out of memory', 1, 'admin@example.com');

Structured Logging

Log structured data as JSON for easier parsing and querying:

<?php
function logEvent(string $level, string $message, array $context = []): void {
    $entry = array_merge([
        'ts'      => date('c'),
        'level'   => $level,
        'message' => $message,
    ], $context);

    error_log(json_encode($entry));
}

logEvent('ERROR', 'Payment failed', [
    'order_id' => 123,
    'amount'   => 99.99,
    'user_id'  => 45,
]);

Log Levels (PSR-3)

PSR-3 defines standard log levels:

  • emergency — system unusable
  • alert — action must be taken
  • critical — critical conditions
  • error — runtime errors
  • warning — exceptional occurrences that aren't errors
  • notice — normal but significant events
  • info — informational messages
  • debug — detailed debug info

Monolog Logger

Monolog is the standard PHP logging library, PSR-3 compatible:

<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('app');
$log->pushHandler(new StreamHandler('/var/log/app.log', Logger::DEBUG));

$log->info('User logged in', ['user_id' => 42]);
$log->error('Payment failed', ['order' => 99, 'reason' => 'card_declined']);
$log->warning('Slow query', ['duration_ms' => 3200]);

Exception Handling in Production

A production-grade exception handler that logs and returns a safe response:

<?php
set_exception_handler(function(\Throwable $e) {
    $id = uniqid('err_');
    error_log(json_encode([
        'error_id' => $id,
        'class'    => get_class($e),
        'message'  => $e->getMessage(),
        'file'     => $e->getFile(),
        'line'     => $e->getLine(),
        'trace'    => $e->getTraceAsString(),
    ]));
    http_response_code(500);
    echo json_encode(['error' => 'Server error', 'id' => $id]);
    exit(1);
});

Log Rotation

Log files grow indefinitely — rotate them with logrotate on Linux or time-based handlers in Monolog:

<?php
use Monolog\Handler\RotatingFileHandler;

$handler = new RotatingFileHandler(
    '/var/log/app.log',
    30,              // keep 30 days
    Logger::DEBUG
);

// Creates dated files: app-2024-05-27.log
$log = new Logger('app');
$log->pushHandler($handler);

Context-Rich Logging

Include request context in every log entry for easier debugging:

<?php
function getRequestContext(): array {
    return [
        'url'     => $_SERVER['REQUEST_URI'] ?? '',
        'method'  => $_SERVER['REQUEST_METHOD'] ?? '',
        'ip'      => $_SERVER['REMOTE_ADDR'] ?? '',
        'user_id' => $_SESSION['user_id'] ?? null,
    ];
}

// Add to every log call:
$log->error('Order failed', array_merge(
    getRequestContext(),
    ['order_id' => $orderId]
));

Avoiding Sensitive Data in Logs

Never log sensitive information:

  • Passwords and tokens
  • Credit card numbers
  • Personal data (GDPR compliance)
  • Full exception stack traces in user-facing responses
<?php
// Bad:
error_log('Login attempt: ' . $email . ' / ' . $password);

// Good:
error_log('Login failed for user: ' . substr($email, 0, 3) . '***');

Sentry and External Error Tracking

In production, use error tracking services like Sentry to centralize and alert on errors:

<?php
// After composer require sentry/sdk
\Sentry\init(['dsn' => getenv('SENTRY_DSN')]);

// Automatic capture of unhandled exceptions
// Manual capture:
try {
    processOrder();
} catch (\Throwable $e) {
    \Sentry\captureException($e);
    throw $e;
}

Assert-Based Preconditions

Use assertions to catch programming errors in development:

<?php
// assert() throws AssertionError when false (dev mode)
assert(is_int($userId), 'userId must be an integer');
assert($amount > 0, 'amount must be positive');

// Or throw explicitly:
if (!is_int($userId)) {
    throw new \InvalidArgumentException('userId must be int');
}

Quick Check

According to PSR-3, which log level indicates a situation that requires immediate attention?

Recap: Error Logging

Logging best practices:

  • Use structured JSON logging with timestamp, level, message, context
  • Follow PSR-3 log levels
  • Use Monolog in production applications
  • Rotate logs to prevent disk fill
  • Never log passwords or sensitive data
  • Use Sentry or similar for real-time error tracking

Frequently asked questions

Is the “Logging Errors and Best Practices” lesson free?

Yes — the full text of “Logging Errors and Best Practices” is free to read here on the web, and the PHP Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the PHP Academy course, upgrade to CoddyKit PRO.

What will I learn in “Logging Errors and Best Practices”?

Log errors to files and follow production error-handling patterns. You practise PHP Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start PHP Academy?

No prior experience is required. PHP Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Logging Errors and Best Practices” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this PHP Academy lesson?

Yes. Every PHP Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. PHP Error Types and Reporting
  2. Try, Catch, and Finally
  3. Creating Custom Exceptions
  4. Logging Errors and Best Practices
← Back to PHP Academy