Logging in PHP Applications: Best Practices in Practice

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Logging in PHP Applications: Best Practices in Practice



Logging is not just about writing errors to a file. It is a strategic tool for monitoring, debugging, and auditing application operation. In this article, we will break down how to organize logging in PHP in practice, using modern approaches and libraries. You will learn how to avoid common mistakes and make logs truly useful.



1. Choosing a Library and the PSR-3 Standard



In the modern PHP community, the de facto standard is the PSR-3 (Logger Interface). It defines a unified set of methods for logging, allowing you to easily change the logging library without rewriting the application code.



The most popular implementation of PSR-3 is the Monolog library. It is flexible, performant, and has many "handlers" for sending logs to files, databases, Slack, Telegram, Email, and cloud services.



Installing Monolog via Composer:



composer require monolog/monolog


Basic usage example:



<?phprequire 'vendor/autoload.php';

use Monolog\\Logger;use Monolog\\Handler\\StreamHandler;

// Create a log channel — usually by application or module name$log = new Logger('my_app');// Add a handler: write logs of level WARNING and above to a file$log->pushHandler(new StreamHandler(__DIR__ . '/logs/app.log', Logger::WARNING));

// Now you can log$log->warning('User {username} attempted to log in with an incorrect password', ['username' => 'ivan']);$log->error('Failed to connect to the database: {error}', ['error' => $e->getMessage()]);?>


Why is this important? Using PSR-3 makes your code independent of a specific library. If tomorrow you want to switch from Monolog to another implementation (e.g., Log4php), you will only need to change the logger initialization, not all the places where $log->error() is called.



2. Log Levels: When to Use What



PSR-3 defines 8 log levels (from lowest to highest priority): DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY. Correct use of levels is the foundation of readable and useful logs.



  • DEBUG — detailed debugging information needed only by the developer (variable values, call traces). Enable only on the dev environment.
  • INFO — important application events: user registered, order created, cron job completed.
  • NOTICE — normal but significant events (e.g., using a deprecated API).
  • WARNING — potential problems that did not stop script execution (failed login attempt, slow database query).
  • ERROR — errors requiring intervention: exceptions, failures in external services.
  • CRITICAL — critical failures: loss of database connection, out of memory.
  • ALERT — immediate administrator action required (site is unavailable).
  • EMERGENCY — the entire system is inoperable.


Practical tip: Configure different handlers for different levels. For example, write WARNING and above to a file, and ERROR and above also send to Telegram/Slack.



// Example: two handlers for one logger$log->pushHandler(new StreamHandler(__DIR__ . '/logs/all.log', Logger::DEBUG));$log->pushHandler(new StreamHandler(__DIR__ . '/logs/errors.log', Logger::ERROR));// For critical errors — send to Telegram$log->pushHandler(new TelegramBotHandler('TOKEN', 'CHAT_ID', Logger::CRITICAL));


3. Structured Logs and Context



One of the

Blogs

Book Recommendations