Search by

ak-flash / laravel-max-logger

ak-flash

Laravel logging channel for MAX with deduplication and rate limiting

Package info

github.com/ak-flash/laravel-max-logger

pkg:composer/ak-flash/laravel-max-logger

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-09-13 18:02 UTC

This package is auto-updated.

Last update: 2026-09-13 18:23:29 UTC


README

Канал логирования Laravel/Monolog, который отправляет ошибки приложения в мессенджер MAX через MAX Bot API.

Packagist · GitHub · CHANGELOG

Требования: PHP 8.2+, Laravel 12, Monolog 3.

Что это и для чего

Пакет добавляет в Laravel канал логирования max: записи лога заданного уровня (по умолчанию error и выше) уходят сообщением в чат или личный диалог MAX. Это способ узнавать об ошибках production-приложения там, где команда уже общается, без развертывания отдельного мониторинга.

Возможности:

  • Отправка ошибок в MAX — репортируемые исключения Laravel и записи Log::error() доставляются в чат или личный диалог; при ответе API Unknown recipient автоматически выполняется повторная отправка через user_id.
  • Дедупликация — одинаковые ошибки не заспамят чат: числа, UUID, email, IPv4 и длинные hex-подстроки нормализуются, повторная отправка блокируется на dedup_ttl секунд, а в следующем уведомлении выводится счётчик duplicates.
  • Ограничение частоты — не более rate_limit попыток доставки за rate_window секунд; подавленные записи накапливаются и отображаются в следующем уведомлении как suppressed.
  • Маскирование — чувствительные ключи контекста (password, token, secret и др.), известный токен бота и явно заданные секретные строки не покидают приложение; email и IPv4 заменяются плейсхолдерами.
  • Защита от гонок — счётчики и доставка защищены cache-блокировкой; ключи изолированы по приложению, окружению и получателю.
  • Отказоустойчивость — сбой MAX API или cache не ломает логирование приложения и не создаёт рекурсию; без credentials канал безопасно отключается через NullHandler.
  • Информативный формат — URL приложения, окружение, уровень, текст, класс и место исключения, ограниченный контекст; длина сообщения контролируется в Unicode-символах.
  • Настраиваемый транспорт — API URL, таймауты, CA-сертификат (системное хранилище или PEM-файл, например Russian Trusted Root CA).

Отправка синхронная: это best-effort уведомления, а не гарантированная очередь доставки.

Установка

Packagist

composer require ak-flash/laravel-max-logger

Из GitHub (VCS)

Добавьте в composer.json приложения:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/ak-flash/laravel-max-logger.git"
        }
    ],
    "require": {
        "ak-flash/laravel-max-logger": "^0.1.0"
    }
}
composer update ak-flash/laravel-max-logger

Локальная копия (разработка пакета)

Склонируйте репозиторий, например в packages/laravel-max-logger рядом с вашим приложением, и подключите по относительному пути:

{
    "repositories": [
        {
            "type": "path",
            "url": "packages/laravel-max-logger",
            "options": {
                "symlink": true,
                "versions": {"ak-flash/laravel-max-logger": "dev-main"}
            }
        }
    ],
    "require": {
        "ak-flash/laravel-max-logger": "dev-main"
    }
}
composer update ak-flash/laravel-max-logger

Настройка канала

Провайдер регистрируется через Laravel auto-discovery. В config/logging.php добавьте канал:

'max' => [
    'driver' => 'custom',
    'via' => \AkFlash\MaxLogger\MaxLoggerFactory::class,
],

При необходимости опубликуйте конфигурацию (необязательно):

php artisan vendor:publish --tag=max-logger-config

В .env задайте:

MAX_LOGGER_TOKEN=your-bot-token
MAX_LOGGER_RECIPIENT_ID=12345
MAX_LOG_LEVEL=error

Добавьте max в список channels нужного стека, например ['single', 'max']. Репортируемые Laravel исключения и записи Log::error() будут проходить через стек. Для отдельного уведомления: Log::channel('max')->error('Ошибка обработки', ['job_id' => 123]);.

Получите токен бота в MAX, узнайте chat_id/user_id (например, через GET /updates Bot API после сообщения боту) и убедитесь, что серверу доступен platform-api2.max.ru.

Настройки

Все значения из config/max-logger.php можно переопределить в описании канала.

Ключ По умолчанию Назначение
enabled true Включение канала; env MAX_LOGGER_ENABLED
token env MAX_LOGGER_TOKEN, fallback MAX_BOT_TOKEN
recipient_id env MAX_LOGGER_RECIPIENT_ID, fallback MAX_CHAT_ID; строковый числовой ID
recipient_type auto chat, user или fallback chat → user при Unknown recipient
level error Минимальный уровень; env MAX_LOG_LEVEL
api_url https://platform-api2.max.ru env MAX_LOGGER_API_URL
timeout / connect_timeout 10 / 3 Таймауты в секундах
ca_path null Системное CA-хранилище или путь к PEM; env MAX_LOGGER_CA_PATH
dedup_ttl 600 Срок дедупликации; 0 отключает; env MAX_LOG_DEDUP_TTL
rate_limit / rate_window 5 / 300 Попытки доставки за окно; rate_limit=0 отключает
cache_store null Cache приложения или именованное хранилище; env MAX_LOGGER_CACHE_STORE
cache_prefix max-logger Префикс ключей
message_limit / context_limit 3900 / 400 Максимальная длина текста и контекста в Unicode-символах
redact_keys / redact_values см. config / [] Маскируемые ключи и явно заданные секретные строки
app_url / environment config приложения Подпись уведомления

Старый ключ канала chat_id поддерживается. Явный recipient_id имеет приоритет. Пустые credentials или enabled=false дают NullHandler.

Доставка и cache

Отправка синхронная, без фонового worker. Одна попытка включает максимум два HTTP-запроса при fallback получателя. Автоматических повторов после сетевого сбоя нет: повторная запись ошибки может попробовать доставку заново, в пределах rate limit.

Дедупликация нормализует числа, UUID, email, IPv4 и длинные hex-значения, учитывает уровень и место исключения. Успешная доставка запускает TTL. Сводки duplicates и suppressed очищаются после успешной отправки.

Хранилище должно поддерживать Laravel LockProvider: стандартные array/file/Redis/database поддерживают locks при правильной настройке. На недоступном или неподдерживаемом cache отправка пропускается. Для нескольких серверов используйте общее хранилище, например Redis. Array действует только внутри процесса; file — в пределах общего файлового пути.

Блокировка получателя защищает счётчики и отправку. Конкурирующая запись при занятой блокировке пропускается без ожидания и не входит в сводку suppressed — это ограничивает задержку обработки исходной ошибки. Ключи изолированы по URL приложения, окружению, токену и получателю. Многопроцессная работа проверена на file и Redis (6 параллельных процессов), реальная доставка подтверждена на staging.

Форматирование и расширение

Сообщение содержит URL приложения, окружение, уровень, текст, класс и место исключения и ограниченный контекст. Вложенные чувствительные ключи маскируются, объекты не сериализуются, глубина и количество элементов ограничены. Токен бота и redact_values удаляются из текста, email/IPv4 заменяются. Маскирование не является универсальным распознаванием персональных данных в свободном тексте.

Можно переопределить container binding MaxClientContract или MessageFormatterContract. При разрешении контракта фабрика передаёт объединённую конфигурацию в параметре options. Важно: фабрика вызывает make() с параметрами, поэтому контейнер игнорирует instance()-биндинги — переопределяйте через bind()-closure, при необходимости читая options из второго аргумента. Для ручной отправки доступен app(MaxClientContract::class)->sendMessage('...'); эта отправка обходит форматирование и лимиты handler.

Диагностика

Если уведомление отсутствует, проверьте credentials, уровень, состав stack, TTL/лимиты, доступность cache и CA-файл. Транспорт возвращает false при ошибке; handler не пишет свои сбои в тот же лог. Для диагностики транспорта используйте контракт клиента и его bool-результат. URL и сырые ответы API с токеном не выводятся.

Отложенные улучшения

  • Retry после сетевого сбоя, метрики недоставки, фоновая отправка через очереди.
  • Универсальное распознавание персональных данных в свободном тексте (сейчас — маскирование по ключам и известным значениям).
  • Совместимость с Laravel 11 и более ранними версиями (matrix-проверка).
  • Оценка поведения «пропуск при занятой блокировке» под боевой нагрузкой.

Разработка

В каталоге пакета:

composer install
composer validate --strict
composer test
composer lint
composer analyse

Тесты используют Orchestra Testbench, fake HTTP и изолированное приложение. CI (.github/workflows/tests.yml) прогоняет проверки на PHP 8.2–8.5.