← Назад к вопросам

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

2.2 Middle🔥 201 комментариев
#Инфраструктура и DevOps

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Мой подход к логированию в PHP-проектах

Логирование — это неотъемлемая часть профессиональной разработки, которую я выстраиваю как многоуровневую систему диагностики, а не просто инструмент для отладки. Вот как я это реализую:

1. Стратегия и уровни логирования

Я использую PSR-3 стандарт с градацией по важности:

use Psr\Log\LoggerInterface;

class OrderService {
    private LoggerInterface $logger;
    
    public function processOrder(Order $order): void {
        $this->logger->info('Начало обработки заказа', [
            'order_id' => $order->getId(),
            'user_id' => $order->getUserId(),
            'amount' => $order->getAmount()
        ]);
        
        try {
            // Бизнес-логика
            $this->logger->debug('Проверка доступности товаров', [
                'items' => $order->getItems()
            ]);
            
        } catch (PaymentException $e) {
            $this->logger->error('Ошибка оплаты заказа', [
                'order_id' => $order->getId(),
                'error_code' => $e->getCode(),
                'gateway_response' => $e->getResponseData() // Без персональных данных!
            ]);
            throw $e;
        }
    }
}

2. Ключевые принципы, которые я соблюдаю

  • Контекст важнее сообщения: всегда добавляю структурированные данные вместо длинного текста
  • Безопасность прежде всего: никогда не логгирую пароли, токены, персональные данные (GDPR/ФЗ-152)
  • Разделение по назначению: разные логи для разных целей:
    • app.log — бизнес-события
    • error.log — ошибки и исключения
    • debug.log — отладочная информация (только на staging)
    • performance.log — метрики производительности
    • audit.log — действия пользователей для аудита

3. Техническая реализация с Monolog

// Конфигурация Monolog с каналами и обработчиками
$logger = new Logger('application');

// В продакшене — пишем в файл с ротацией
$logger->pushHandler(new RotatingFileHandler(
    '/var/log/app/production.log',
    30, // Храним 30 дней
    Logger::INFO
));

// Для ошибок — отдельный файл с уведомлениями
$errorHandler = new StreamHandler('/var/log/app/errors.log', Logger::ERROR);
$errorHandler->setFormatter(new JsonFormatter()); // JSON для парсинга ELK
$logger->pushHandler($errorHandler);

// В разработке — выводим в консоль
if ($env === 'dev') {
    $logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
}

// Sentry для критических ошибок
$logger->pushHandler(new SentryHandler(Sentry\ClientBuilder::create(), Logger::ERROR));

4. Структурирование логов для аналитики

Я настраиваю логи в формате, удобном для систем типа ELK Stack или Grafana/Loki:

{
  "timestamp": "2024-01-15T14:30:00+03:00",
  "level": "ERROR",
  "channel": "payment",
  "message": "Payment gateway timeout",
  "context": {
    "order_id": 12345,
    "gateway": "stripe",
    "attempt": 3,
    "duration_ms": 12050
  },
  "extra": {
    "app_version": "2.1.0",
    "environment": "production",
    "trace_id": "abc-123-def-456"
  }
}

5. Автоматическое логирование через middleware/interceptors

// Middleware для логирования HTTP-запросов
class RequestLoggerMiddleware {
    public function handle(Request $request, Closure $next) {
        $start = microtime(true);
        
        $response = $next($request);
        
        $duration = (microtime(true) - $start) * 1000;
        
        $this->logger->info('HTTP Request', [
            'method' => $request->method(),
            'url' => $request->path(),
            'status' => $response->status(),
            'duration_ms' => round($duration, 2),
            'ip' => $request->ip(),
            'user_agent' => substr($request->userAgent(), 0, 200)
        ]);
        
        return $response;
    }
}

6. Производительность и ротация

  • Буферизация логов для минимизации I/O операций
  • Асинхронная запись через обработчики типа FingersCrossedHandler
  • Автоматическая ротация по размеру или времени
  • Разделение по датам для упрощения архивации

7. Что я никогда не делаю

  • ❌ Не использую var_dump() или echo для отладки
  • ❌ Не логгирую в общий файл без ротации
  • ❌ Не оставляю логи уровня DEBUG в production
  • ❌ Не забываю про контекст — "что сломалось" и "при каких условиях"

8. Мониторинг и алертинг

Настраиваю оповещения при:

  • Резком росте ошибок определенного типа
  • Критических исключениях (через Sentry/Telegram)
  • Долгих операциях (медленнее порогового значения)

Итог: мой подход к логированию — это продуманная система observability, которая превращает сырые данные в actionable insights для разработки, поддержки и бизнеса. Логи становятся не архивом ошибок, а инструментом для принятия решений о развитии системы.