Monolog для PHP: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое Monolog и зачем он нужен?

Monolog — это стандартная библиотека для логирования в PHP. Она предоставляет гибкий и мощный инструментарий для записи логов в различные каналы (файлы, базы данных, электронную почту, системный журнал, внешние сервисы и т.д.). Monolog является де-факто стандартом для PHP-приложений, особенно в экосистеме Symfony, Laravel и других современных фреймворков.

Зачем нужна эта библиотека? В любом приложении необходимо отслеживать события: ошибки, предупреждения, информационные сообщения, отладочную информацию. Monolog позволяет:

  • Централизовать логирование — писать логи в одном формате и из любого места приложения.
  • Гибко настраивать каналы — отправлять критические ошибки в Telegram/Slack, а информационные сообщения — в файл.
  • Форматировать сообщения — добавлять дату, уровень, контекст, стек вызовов.
  • Фильтровать логи — обрабатывать только сообщения определённого уровня.
  • Интегрироваться с фреймворками — в Symfony, Laravel, Yii2 используется именно Monolog.

Установка

Monolog устанавливается через Composer — стандартный менеджер пакетов для PHP.

composer require monolog/monolog

Если вы используете PHP 8.0+, рекомендуется устанавливать последнюю стабильную версию. После установки в проекте появится папка vendor и файл composer.json с зависимостью.

Быстрый старт

Самый простой пример — запись лога в файл:

<?php
require 'vendor/autoload.php';

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

// Создаём логгер с именем канала 'my_app'
$log = new Logger('my_app');
// Добавляем обработчик — запись в файл
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));

// Теперь можно логировать
$log->warning('Это предупреждение');
$log->error('Это ошибка');

echo "Логи записаны в app.log";
?>

После выполнения скрипта в файле app.log появится что-то вроде:

[2025-04-09T10:30:00.123456+00:00] my_app.WARNING: Это предупреждение [] []
[2025-04-09T10:30:00.123789+00:00] my_app.ERROR: Это ошибка [] []

Основные методы и функции

Рассмотрим ключевые методы Monolog. Все они являются частью класса Monolog\Logger или связанных классов.

1. pushHandler(HandlerInterface $handler)

Что делает: Добавляет обработчик (handler) в стек. Логгер может иметь несколько обработчиков, и каждый из них будет получать все сообщения (если не настроена фильтрация).

Параметры:

  • $handler — объект, реализующий Monolog\Handler\HandlerInterface (например, StreamHandler, FirePHPHandler, SlackHandler).

Пример:

$log = new Logger('app');
$log->pushHandler(new StreamHandler('debug.log', Logger::DEBUG));
$log->pushHandler(new StreamHandler('errors.log', Logger::ERROR));
// Теперь сообщения уровня ERROR и выше попадут в оба файла

2. addRecord(int $level, string $message, array $context = [])

Что делает: Базовый метод для записи лога. Обычно не вызывается напрямую, вместо него используются методы-обёртки (debug(), info() и т.д.).

Параметры:

  • $level — уровень логирования (константы: Logger::DEBUG, Logger::INFO, Logger::WARNING и т.д.).
  • $message — текст сообщения.
  • $context — массив дополнительных данных (например, ID пользователя, IP-адрес).

Пример:

$log->addRecord(Logger::INFO, 'Пользователь вошёл в систему', ['user_id' => 42]);

3. debug(string $message, array $context = [])

Что делает: Записывает отладочное сообщение (уровень DEBUG — 100). Используется для детальной информации, полезной при разработке.

Параметры: те же, что и у addRecord.

Пример:

$log->debug('SQL запрос выполнен за {time} ms', ['time' => 12.5]);

4. info(string $message, array $context = [])

Что делает: Записывает информационное сообщение (уровень INFO — 200). Обычно используется для отслеживания нормального хода работы приложения.

Пример:

$log->info('Крон-задача выполнена успешно', ['task' => 'send_emails']);

5. warning(string $message, array $context = [])

Что делает: Записывает предупреждение (уровень WARNING — 300). Указывает на потенциальную проблему, которая не является критической.

Пример:

$log->warning('Диск заполнен на 90%', ['disk_usage' => 90]);

6. error(string $message, array $context = [])

Что делает: Записывает ошибку (уровень ERROR — 400). Приложение продолжает работу, но произошёл сбой.

Пример:

$log->error('Не удалось подключиться к БД', ['db_host' => 'localhost', 'error' => $e->getMessage()]);

7. critical(string $message, array $context = [])

Что делает: Записывает критическую ошибку (уровень CRITICAL — 500). Приложение может быть частично недоступно.

Пример:

$log->critical('Исчерпан лимит памяти', ['memory_limit' => ini_get('memory_limit')]);

8. alert(string $message, array $context = [])

Что делает: Записывает тревожное сообщение (уровень ALERT — 550). Требуется немедленное вмешательство администратора.

Пример:

$log->alert('Сервер атакован!', ['ip' => '192.168.1.1', 'attempts' => 1000]);

9. emergency(string $message, array $context = [])

Что делает: Самый высокий уровень (EMERGENCY — 600). Система полностью неработоспособна.

Пример:

$log->emergency('Полный отказ системы', ['uptime' => 0]);

10. pushProcessor(callable $processor)

Что делает: Добавляет процессор — функцию, которая модифицирует запись лога перед отправкой обработчикам. Например, можно автоматически добавлять IP-адрес или ID сессии.

Параметры:

  • $processor — callable, принимающий массив записи лога и возвращающий его.

Пример:

$log->pushProcessor(function ($record) {
    $record['extra']['ip'] = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    return $record;
});
$log->info('Тест'); // В логе появится extra.ip

11. popHandler()

Что делает: Удаляет последний добавленный обработчик из стека.

Пример:

$log->pushHandler(new StreamHandler('temp.log'));
$log->info('Сообщение уйдёт в temp.log');
$log->popHandler(); // Удаляем обработчик
$log->info('Это сообщение уже никуда не попадёт');

Реальный практический пример использования

Рассмотрим полноценный пример — логирование действий пользователя в веб-приложении с отправкой критических ошибок в Telegram.

<?php
require 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\TelegramBotHandler;
use Monolog\Processor\IntrospectionProcessor;

// Создаём логгер
$logger = new Logger('user_actions');

// 1. Обработчик для записи всех логов в файл
$fileHandler = new StreamHandler(__DIR__ . '/logs/app.log', Logger::DEBUG);
$logger->pushHandler($fileHandler);

// 2. Обработчик для отправки критических ошибок в Telegram
$telegramHandler = new TelegramBotHandler(
    'YOUR_BOT_TOKEN', // Токен бота
    'YOUR_CHAT_ID',   // ID чата
    Logger::CRITICAL  // Только CRITICAL и выше
);
$logger->pushHandler($telegramHandler);

// 3. Добавляем процессор для включения стека вызовов
$logger->pushProcessor(new IntrospectionProcessor());

// Симуляция действий пользователя
function processOrder($orderId, $logger) {
    try {
        // Логируем начало обработки
        $logger->info('Начало обработки заказа', ['order_id' => $orderId]);
        
        // Имитация ошибки
        if ($orderId <= 0) {
            throw new \InvalidArgumentException('Некорректный ID заказа');
        }
        
        // Успешное завершение
        $logger->info('Заказ обработан', ['order_id' => $orderId]);
        
    } catch (\Exception $e) {
        // Критическая ошибка — уйдёт и в файл, и в Telegram
        $logger->critical('Ошибка обработки заказа', [
            'order_id' => $orderId,
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString()
        ]);
    }
}

processOrder(123, $logger);
processOrder(-1, $logger);

echo "Логирование завершено. Проверьте logs/app.log и Telegram.";
?>

В этом примере:

  • Все сообщения пишутся в файл app.log.
  • Сообщения уровня CRITICAL и выше дополнительно отправляются в Telegram.
  • Добавлен процессор IntrospectionProcessor, который добавляет информацию о файле и строке, откуда был вызван логгер.

Советы и типичные ошибки

Советы:

  1. Используйте разные каналы — создавайте отдельные логгеры для разных частей приложения (например, database, auth, payment). Это упрощает анализ.
  2. Настраивайте уровни логирования — на продакшене не пишите DEBUG-логи в файл, иначе он быстро переполнится. Используйте Logger::WARNING или выше.
  3. Используйте контекст — передавайте в $context максимум полезной информации (ID пользователя, IP, URL). Это сильно помогает при отладке.
  4. Ротация логов — используйте RotatingFileHandler для автоматической ротации файлов логов по дням.
  5. Не логируйте пароли и токены — это угроза безопасности. Если нужно, используйте процессоры для маскировки.

Типичные ошибки:

  1. Забыли вызвать pushHandler — без обработчика лог

Рекомендаций