Как используешь логирование?

«Как используешь логирование?» — вопрос из категории DevOps, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В PHP-проектах я использую библиотеку Monolog как стандарт де-факто для структурированного логирования. Моя типичная настройка включает несколько обработчиков (handlers) для разных целей.

Базовый пример инициализации логгера:

use MonologLogger;
use MonologHandlerStreamHandler;
use MonologHandlerRotatingFileHandler;

$log = new Logger('my_app');

// Основной лог-файл с ротацией по дням
$log->pushHandler(new RotatingFileHandler('/var/log/app/app.log', 7, Logger::DEBUG));

// Отдельный лог для критических ошибок
$log->pushHandler(new StreamHandler('/var/log/app/critical.log', Logger::CRITICAL));

// Логирование в консоль для разработки
if (getenv('APP_ENV') === 'dev') {
    $log->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
}

Ключевые практики, которые я применяю:

  • Контекстное логирование: Всегда добавляю контекст для событий, чтобы облегчить поиск причин.
    $log->error('Failed to process payment', [
        'order_id' => $orderId,
        'gateway' => $gatewayName,
        'user_id' => $userId
    ]);
  • Разные уровни для разных сред: В development — DEBUG, в production — INFO и выше, чтобы не засорять логи.
  • Централизованный сбор в продакшене: Для production-среды настраиваю отправку логов в Sentry (для ошибок) и ELK-стек (Graylog, Loki) для агрегации и анализа, вместо хранения в локальных файлах.
  • Обработка PHP-ошибок: Перенаправляю все ошибки PHP в логгер через set_error_handler() и фатальные ошибки/исключения через set_exception_handler() и register_shutdown_function().