Search by

cloud-castle / grafana-loki

Полный клиент Grafana Loki для PHP 8.1+: push с батчингом, gzip, повторами и резервным каналом; Query API с LogQL и живым tail; PSR-3 логгер и мосты Monolog/cloud-castle; маскирование секретов и in-memory Loki для тестов.

Maintainers

Package info

gitverse.ru/cloud-castle/grafana-loki

Homepage

Issues

Documentation

pkg:composer/cloud-castle/grafana-loki

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

v1.1.0 2026-09-03 07:32 UTC

README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle Grafana Loki

CloudCastle Grafana Loki

Полный клиент Grafana Loki для PHP 8.1+: запись и чтение журналов. Push с батчингом, сжатием, повторами и резервным каналом; Query API с LogQL, живой tail, PSR-3 логгер, маскирование секретов и in-memory Loki для тестов.

Packagist

Packagist Version PHP Version License Downloads Monthly Downloads Stars

Репозиторий

GitVerse Issues Wiki Release

Качество кода

PHPStan Psalm PHPMD PHPCS Deptrac

Зачем он нужен

Каждый существующий Loki-пакет для PHP — это хендлер для одного фреймворка или логгера: он умеет отправлять строки и больше ничего. Читать журналы, строить LogQL-запросы, переживать недоступность сервера, не светить секреты — всё это оставалось за кадром.

Этот пакет закрывает работу с Loki целиком:

  • Запись — батчинг с группировкой потоков, gzip, повторы с выдержкой и уважением Retry-After, предохранитель, резервный канал (файл/error_log/своё), строго возрастающие наносекундные метки, structured metadata Loki 3.x.
  • Чтениеquery, query_range, метки, серии, статистика индекса, patterns/detected_labels/detected_fields, живой tail поллингом без WebSocket.
  • LogQL — типобезопасный строитель запросов с экранированием и валидацией.
  • Интеграции — родной PSR-3 логгер, мосты Monolog 3 и cloud-castle/logger, транспорт на cURL/потоках/любом PSR-18 клиенте.
  • Безопасность — маскирование паролей, токенов и платёжных карт (Луна), запрет учётных данных в URL, анти-SSRF режим, секреты не сериализуются.
  • ТестируемостьFakeLokiTransport: полный цикл записи и чтения в памяти процесса, симуляция отказов сервера одной строкой.

Установка

composer require cloud-castle/grafana-loki

Требуется PHP 8.1+. Расширения не обязательны: ext-curl и ext-zlib подключаются автоматически, если собраны; без них работает потоковый транспорт без сжатия.

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

use CloudCastle\Grafana\Loki\Configuration\LokiConfig;
use CloudCastle\Grafana\Loki\LokiClient;

$client = new LokiClient(new LokiConfig('http://loki:3100', labels: ['app' => 'shop']));

// Запись: буферизуется и уходит батчами автоматически
$client->push('заказ создан', ['module' => 'orders'], ['order_id' => 42]);
$client->flush();

// PSR-3 логгер поверх того же клиента
$logger = $client->logger(['component' => 'billing']);
$logger->error('оплата отклонена: {reason}', ['reason' => 'недостаточно средств']);
$client->flush();

// Чтение: LogQL за последние 15 минут
$result = $client->queries()->queryRange('{app="shop"} |= "заказ"', '-15 minutes', 'now');

foreach ($result->entries() as $entry) {
    echo $entry->timestampNs, ' ', $entry->line, PHP_EOL;
}

Строитель LogQL вместо строковой конкатенации:

use CloudCastle\Grafana\Loki\LogQL\{AggregationOp, LogQLBuilder, RangeFunction};

$logql = (new LogQLBuilder())
    ->withLabel('app', 'shop')
    ->withLineContains('error')
    ->withJson()
    ->withWhere('status', '>=', 500)
    ->build();
// {app="shop"} |= "error" | json | status>=500

$metric = (new LogQLBuilder())
    ->withLabel('app', 'shop')
    ->range(RangeFunction::Rate, '5m')
    ->aggregate(AggregationOp::Sum, groupBy: ['status'])
    ->build();
// sum by (status) (rate({app="shop"}[5m]))

Тестирование своего кода без сервера Loki:

use CloudCastle\Grafana\Loki\Testing\FakeLokiTransport;

$fake = new FakeLokiTransport();
$client = new LokiClient(new LokiConfig('http://loki.test'), transport: $fake);

$client->push('оплата проведена', ['app' => 'billing']);
$client->flush();

self::assertCount(1, $fake->entries('{app="billing"} |= "оплата"'));

$fake->failNext(503, times: 2);   // симуляция отказов — проверка повторов

Grafana Cloud (мультитенантный Loki с токеном):

use CloudCastle\Grafana\Loki\Auth\BearerAuth;

$config = new LokiConfig(
    'https://logs-prod-eu-west-0.grafana.net',
    auth: new BearerAuth($token),
    tenantId: '123456',
);

Сравнение с аналогами

Все таблицы генерируются автоматически из замеров и анализа исходников (composer docs:build); руками цифры не пишутся. Подробности методики — на странице сравнения в wiki.

Функциональность

ВозможностьCloudCastleitspiretomas-kulhanekfelipetekocebe/yii2alexmacarthur
Отправка логов в Loki (push API)
Батчинг записей из коробки
Несколько потоков меток в одном батче
Сжатие gzip
Повторы с экспоненциальной выдержкой и джиттером
Уважение заголовка Retry-After
Предохранитель (circuit breaker)
Резервный приёмник недоставленных записей
Строго возрастающие наносекундные метки времени
Структурированные метаданные (Loki 3.x)
Мультитенантность (X-Scope-OrgID)
Basic-аутентификация
Bearer-токен из коробки
mTLS (клиентский сертификат) параметром конфигурации
Настройка таймаутов соединения и запроса
Работа без ext-curl (потоковый транспорт)
Подключение любого PSR-18 клиента
Родной PSR-3 логгер без Monolog
Интеграция с Monolog
Чтение: мгновенные и range-запросы (LogQL)
Чтение: имена и значения меток
Чтение: series, index stats, volume, patterns
Живой tail без WebSocket
Типобезопасный строитель LogQL
In-memory Loki для тестов пользователя
Маскирование секретов и платёжных данных
Валидация имён меток до отправки
Встроенные счётчики доставки (наблюдаемость)
Итого возможностей2855355
🏆 Победитель🏆

Безопасность

Механизм защитыCloudCastleitspiretomas-kulhanekfelipetekocebe/yii2alexmacarthur
Полная проверка TLS-сертификата по умолчанию
Редиректы транспорта не выполняются
Валидация адреса сервера при конфигурации (схемы)
Запрет учётных данных в URL
Режим блокировки приватных адресов (анти-SSRF)
Учётные данные не сериализуются
Пароль/токен скрыты из var_dump
Пароль не попадает в стектрейсы (SensitiveParameter)
Маскирование номеров карт (PAN, проверка Луна)
Маскирование секретных ключей контекста
Усечение тел ошибок сервера в исключениях
Ответы сервера не пишутся в error_log
Итого возможностей1234222
🏆 Победитель🏆

Производительность: одиночные записи

Доставка одиночных записей: 300 операций «запись → HTTP-доставка» на общий приёмник (реалистичная сетевая задержка), медиана 9 прогонов.

ПакетВремя🏆 Победитель
CloudCastle395.8 мс🏆
itspire397.2 мс
tomas-kulhanek402.9 мс
cebe/yii2405.1 мс
felipeteko449.7 мс
alexmacarthur502 мс

Производительность: пакетная доставка

Доставка пакета: 2000 записей по нескольким потокам меток (реальный сервис; реалистичная сетевая задержка), медиана 9 прогонов.

ПакетВремя🏆 Победитель
CloudCastle9.9 мс🏆
cebe/yii233.2 мс
alexmacarthur36 мс
tomas-kulhanek39 мс
itspire2 668.9 мс
felipeteko2 947.8 мс

Потребление памяти

Память самой библиотеки: пик рабочей фазы (500 доставок) минус baseline, снятый до создания клиента в изолированном процессе — стоимость PHP и автолоадера вычтена.

ПакетПамять🏆 Победитель
itspire412 KB🏆
felipeteko439 KB
tomas-kulhanek483 KB
CloudCastle578 KB
cebe/yii21 749 KB
alexmacarthur4 758 KB

Утечки памяти

_Рост удержанной памяти за 3 000 доставок после прогрева и gc_collectcycles (изолированный процесс; 0 — утечек нет).

ПакетРост🏆 Победитель
CloudCastle0 KB🏆
itspire0 KB🏆
tomas-kulhanek0 KB🏆
felipeteko0 KB🏆
cebe/yii20 KB🏆
alexmacarthur0 KB🏆

Качество кода

МетрикаCloudCastleitspiretomas-kulhanekfelipetekocebe/yii2alexmacarthur🏆 Победитель
Синтаксические ошибки (php -l)000000CloudCastle, itspire, tomas-kulhanek, felipeteko, cebe/yii2, alexmacarthur 🏆
Файлы со strict_types, %100100100000CloudCastle, itspire, tomas-kulhanek 🏆
final-классы, %9900000CloudCastle 🏆
Runtime-зависимостей211125itspire, tomas-kulhanek, felipeteko 🏆
Файлов исходников10224115felipeteko, cebe/yii2 🏆
Минимальная версия PHP>=8.1~8.1>=8.2>=7.1.0^8.1

Возможности проверены по исходникам пакетов (каталог vendor окружения сравнения). Отметка «есть» ставится за возможность из коробки, без правки кода пакета.

felipeteko/monolog-loki пишет ответ сервера в error_log на каждую запись — в замерах это его штатное поведение.

cebe/yii2-loki-log-target и alexmacarthur/laravel-loki-logging привязаны к своим фреймворкам; в изолированном замере им поднято минимальное окружение.

Замер выполнен 2026-09-03 на PHP 8.3.33.

Честно о плюсах и минусах

Плюсы:

  • Единственный PHP-клиент с Query API: журналы можно не только писать, но и читать, строить по ним выборки и живой tail — прямо из кода.
  • Самая быстрая пакетная доставка среди аналогов и первое место в одиночных отправках (замеры в таблицах выше, обновляются автоматически).
  • Контур отказоустойчивости целиком: повторы, предохранитель, резервный канал — журналирование не роняет приложение и не теряет записи молча.
  • Маскирование секретов и платёжных данных включено по умолчанию.
  • In-memory Loki для тестов — код, пишущий и читающий журналы, тестируется без единого контейнера.

Минусы:

  • Пакет моложе и менее распространён, чем itspire/monolog-loki и другие ветераны: меньше установок, меньше отзывов сообщества.
  • Потребление памяти выше, чем у минималистичных хендлеров на один класс (545 KB против 400 KB у самого лёгкого): цена суперсета функционала. Если нужен именно один класс без зависимостей — минималисты легче.
  • Отправка protobuf+snappy не реализована — используется JSON+gzip (штатный формат Loki; protobuf в планах).

Где и когда применять

  • Финтех и всё, где есть ПД — маскирование карт и секретов из коробки, fail-safe доставка, режим ErrorMode::Throw для конвейеров, где потеря журнала должна останавливать обработку.
  • Долгоживущие воркеры и демоны (queue-консьюмеры, Swoole/RoadRunner) — батчинг, keep-alive соединение, предохранитель и подтверждённое отсутствие утечек памяти.
  • Инструменты и панели на данных Loki — Query API с типизированными результатами и строитель LogQL вместо конкатенации строк.
  • Laravel/Symfony/любой фреймворк с Monolog — мост MonologHandler добавляет весь контур надёжности к привычному логгеру.
  • Когда достаточно «просто слать строки» в маленьком скрипте без требований к надёжности — подойдёт и минималистичный хендлер; этот пакет раскрывается там, где журналы — часть продукта, а не побочный эффект.

Документация

Разработка

composer install
composer check        # линтеры + статанализ + тесты
composer test:full    # полный порядок: phplint → psalm → phpstan → phpmd → phpcs →
                      # rector → deptrac → мутации → безопасность → память → утечки →
                      # производительность → качество
composer docs:build   # замеры против аналогов + генерация таблиц (PHP 8.2+, benchmarks/vendor)

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano