TGViewer
Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter @phpproglib · 10.5K subscribers
Post #6332 2.46K
⌛️ Как настроить production-ready логирование в PHP

Логи в проде — это не просто error_log(). Это структурированные данные, correlation ID, асинхронная запись и ротация. Разбираем пошаговую настройку.

1️⃣ Выбираем стек: Monolog

PHP де-факто стандарт для логирования — Monolog. Устанавливаем через Composer:

composer require monolog/monolog


Если на Laravel, уже есть из коробки. Если нет, то подключаем вручную.

2️⃣ Базовая конфигурация с JSON-форматом

use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\JsonFormatter;

$log = new Logger('app');

$handler = new RotatingFileHandler(
__DIR__ . '/logs/application.log',
maxFiles: 30,
level: Logger::INFO
);

$handler->setFormatter(new JsonFormatter());
$log->pushHandler($handler);


JSON-формат удобен для парсинга в ELK / Grafana Loki.

3️⃣ Добавляем Correlation ID

Трекаем каждый запрос через Processor:

class CorrelationIdProcessor implements ProcessorInterface
{
private string $correlationId;

public function __construct()
{
$this->correlationId = $_SERVER['HTTP_X_CORRELATION_ID']
?? bin2hex(random_bytes(16));

header('X-Correlation-ID: ' . $this->correlationId);
}

public function __invoke(array $record): array
{
$record['extra']['correlation_id'] = $this->correlationId;
return $record;
}
}

$log->pushProcessor(new CorrelationIdProcessor());


Теперь каждая строка лога привязана к конкретному запросу.

4️⃣ Ротация и лимиты

$handler = new RotatingFileHandler(
filename: __DIR__ . '/logs/app.log',
maxFiles: 30,
level: Logger::WARNING,
);


Для ограничения по размеру связываем с logrotate на уровне системы:

# /etc/logrotate.d/php-app
/var/www/app/logs/*.log {
daily
rotate 30
compress
missingok
size 100M
}


5️⃣ Асинхронная запись

PHP синхронный по природе, но можно буферизовать тяжёлые хендлеры:

use Monolog\Handler\BufferHandler;

$bufferHandler = new BufferHandler(
handler: new StreamHandler('logs/app.log'),
bufferSize: 100,
flushOnOverflow: true
);

$log->pushHandler($bufferHandler);


Буферизуем записи и сбрасываем пачкой → меньше I/O операций.

6️⃣ Интеграция с мониторингом

Отправляем в Graylog через GELF:

use Monolog\Handler\GelfHandler;
use Gelf\Publisher;
use Gelf\Transport\UdpTransport;

$publisher = new Publisher(
new UdpTransport('logstash.example.com', 12201)
);

$log->pushHandler(new GelfHandler($publisher));


Или напрямую в Telegram для критических ошибок. Отдельный хендлер, 5 минут работы.

📌 Итог

Monolog + JsonFormatter + CorrelationId + logrotate = логи, с которыми не стыдно идти в прод.

Библиотека пхпшника
  • 👍 11
  • ❤ 2
  • 🔥 2
More from @phpproglib
  1. Sep 23, 2026🛠 Symfony 8.2 научился автоматически генерировать JSON Schema для конфигурации приложения…
  2. Sep 23, 2026🚀 Свежий релиз Laravel 13 с набором улучшений и исправлений ✅ добавлена поддержка valkey:…
  3. Sep 21, 2026⚡️ PHP 8.6 выйдет 19 ноября 2026 года. Сейчас версия находится в beta. Самые заметные изме…
  4. Sep 20, 2026❓ Какие существуют проблемы в многопоточной среде? Основные проблемы многопоточности: 1️⃣…
  5. Sep 19, 2026🌞 В Symfony 8.2 появилось 29 новых Bundle — теперь компоненты вроде Mailer, Messenger и C…
  6. Sep 19, 2026А вы уже забрали свой подарок ко Дню программиста? К вашему профессиональному празднику Tp…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →