Привет, Хабр! Меня зовут Александр Белышев. Хочу немного вам рассказать о библиотеке (Laravel Zipkin Tracer), которую я разработал изучая трейсинг в php, возможно кому-то это будет так же интересно, как и мне. О OpenTelemetry я знал что он есть, даже его пощупал, но хотелось чуть с другой стороны изучить предмет и решить его несколько другим способом.
Laravel Zipkin Tracer — это специализированный модуль для Laravel, который обеспечивает автоматический трейсинг HTTP‑запросов, SQL‑запросов и позволяет создавать пользовательские спаны (spans) для интеграции с Zipkin.
Архитектура модуля
Модуль состоит из нескольких ключевых компонентов:
-
ZipkinTracerProvider — основной провайдер, регистрирующий все сервисы
-
ZipkinTracerMiddleware — middleware для перехвата HTTP‑запросов
-
EventSubscriber — подписчик на события Laravel для автоматического трейсинга
-
DataCollectorService — сервис для сбора и сохранения данных трейсинга
-
CustomSpanService — сервис для создания пользовательских спанов
-
SyncDataCommand — команда для синхронизации данных с Zipkin
Общая архитектура системы
Детальная схема сбора данных
Установка и настройка
Требования
-
PHP ^8.2
-
Laravel ^10
-
openzipkin/zipkin ^3.2
Установка
composer require xman12/laravel-zipkin-tracer
Настройка
-
Добавление провайдера в
app/bootstrap/providers.php:return [ App\Providers\AppServiceProvider::class, ZipkinTracerProvider::class, ]; -
Копирование конфигурации:
php artisan vendor:publish --tag=zipkin-tracer -
Настройка переменных окружения в
.env:ZIPKIN_TRACER_ENABLE=true ZIPKIN_TRACER_STORAGE_PATH=/path/to/storage/zipkin_tracer ZIPKIN_TRACER_SERVICE_NAME=my-service ZIPKIN_TRACER_ENDPOINT=http://127.0.0.1:9411/api/v2/spans -
Настройка cron для синхронизации данных:
# Добавить в crontab * * * * * php artisan zipkin-tracer:sync_data
Функциональность
Модуль автоматически отслеживает:
HTTP-запросы
-
Метод запроса (GET, POST, PUT, DELETE)
-
URL
-
Статус код ответа
-
Размер запроса и ответа
-
Время выполнения
-
Исключения
SQL-запросы
-
Текст SQL‑запроса
-
Время выполнения
-
Файл и строка выполнения
-
Транзакции (begin, commit, rollback)
HTTP-клиент запросы
-
Исходящие HTTP‑запросы через Laravel HTTP Client
-
Заголовки запросов
-
Статус коды ответов
-
Ошибки соединения
Пользовательские спаны
Модуль позволяет создавать собственные спаны для отслеживания бизнес‑логики:
/** @var CustomSpanService $customSpanService */ $customSpanService = app(CustomSpanService::class); // Простой спан $span = $customSpanService->createSpan('user-registration', function () { // Бизнес-логика регистрации пользователя $user = User::create([ 'name' => 'John Doe', 'email' => 'john@example.com' ]); return [ 'user_id' => $user->id, 'registration_method' => 'email' ]; }); $customSpanService->addSpan($span);
Вложенные спаны
// Дочерние спаны $validationSpan = $customSpanService->createSpan('validate-user-data', function () { // Валидация данных return ['validation_passed' => true]; }); $emailSpan = $customSpanService->createSpan('send-welcome-email', function () { // Отправка приветственного письма return ['email_sent' => true]; }); // Родительский спан с дочерними $mainSpan = $customSpanService->createSpan('user-registration-process', function () { // Основная логика return ['process_completed' => true]; }, [$validationSpan, $emailSpan]); $customSpanService->addSpan($mainSpan);
Процесс сбора данных
Процесс синхронизации с Zipkin
Сравнение с OpenTelemetry
В процессе изучения вопроса, я естественно столкнулся с OpenTelemetry. Я его изучил, пощупал, но как писал выше мне хотелось решить задачу другим методом, чуть менее зависимым и чуть более предсказуемым хотя возможно это не совсем и правильный путь.
Laravel Zipkin Tracer vs OpenTelemetry
|
Характеристика |
Laravel Zipkin Tracer |
OpenTelemetry |
|---|---|---|
|
Специализация |
Специально для Laravel + Zipkin |
Универсальный стандарт |
|
Сложность настройки |
Простая |
Средняя-высокая |
|
Автоматический трейсинг |
✅ HTTP, SQL, HTTP Client |
✅ Более широкий спектр |
|
Пользовательские спаны |
✅ Простой API |
✅ Более сложный API |
|
Производительность |
Высокая (минимальные накладные расходы) |
Средняя (больше метаданных) |
|
Интеграция с Laravel |
Нативная |
Требует дополнительной настройки |
|
Поддержка стандартов |
Zipkin-specific |
OpenTelemetry standard |
|
Экосистема |
Ограниченная |
Огромная |
Преимущества Laravel Zipkin Tracer
-
Простота использования
-
Минимальная конфигурация
-
Автоматическая интеграция с Laravel
-
Понятный API для пользовательских спанов
-
-
Производительность
-
Асинхронная отправка данных
-
Минимальные накладные расходы
-
Эффективное хранение в файловой системе
-
-
Специализация
-
Оптимизирован для Laravel
-
Готовая интеграция с Zipkin
-
Автоматический трейсинг типичных сценариев
-
Недостатки Laravel Zipkin Tracer
-
Ограниченная экосистема
-
Только Zipkin
-
Меньше инструментов и интеграций
-
-
Функциональность
-
Меньше возможностей по сравнению с OpenTelemetry
-
Ограниченные возможности для метрик
-
-
Стандартизация
-
Не следует открытым стандартам
-
Может быть сложнее мигрировать в будущем
-
Практические примеры
Пример 1: Трейсинг API-эндпоинта
// UserController.php class UserController extends Controller { public function show($id) { /** @var CustomSpanService $customSpanService */ $customSpanService = app(CustomSpanService::class); $user = User::with(['profile', 'posts'])->findOrFail($id); $span = $customSpanService->createSpan('get-user-profile', function () use ($user) { return [ 'user_id' => $user->id, 'profile_complete' => $user->profile ? true : false, 'posts_count' => $user->posts->count() ]; }); $customSpanService->addSpan($span); return response()->json($user); } }
Пример 2: Трейсинг внешних API-вызовов
// ExternalApiService.php class ExternalApiService { public function fetchUserData($userId) { /** @var CustomSpanService $customSpanService */ $customSpanService = app(CustomSpanService::class); $span = $customSpanService->createSpan('external-api-call', function () use ($userId) { // Laravel HTTP Client автоматически трейсится $response = Http::get("https://api.external.com/users/{$userId}"); return [ 'external_user_id' => $userId, 'response_status' => $response->status(), 'response_size' => strlen($response->body()) ]; }); $customSpanService->addSpan($span); return $response->json(); } }
Пример 3: Трейсинг сложной бизнес-логики
// OrderService.php class OrderService { public function processOrder($orderData) { /** @var CustomSpanService $customSpanService */ $customSpanService = app(CustomSpanService::class); // Валидация заказа $validationSpan = $customSpanService->createSpan('validate-order', function () use ($orderData) { $validator = Validator::make($orderData, [ 'items' => 'required|array', 'customer_id' => 'required|exists:customers,id' ]); if ($validator->fails()) { throw new ValidationException($validator); } return ['validation_passed' => true]; }); // Проверка наличия товаров $inventorySpan = $customSpanService->createSpan('check-inventory', function () use ($orderData) { foreach ($orderData['items'] as $item) { $product = Product::find($item['product_id']); if ($product->stock < $item['quantity']) { throw new InsufficientStockException(); } } return ['inventory_available' => true]; }); // Создание заказа $orderSpan = $customSpanService->createSpan('create-order', function () use ($orderData) { DB::transaction(function () use ($orderData) { $order = Order::create([ 'customer_id' => $orderData['customer_id'], 'total_amount' => $this->calculateTotal($orderData['items']) ]); foreach ($orderData['items'] as $item) { $order->items()->create($item); } }); return ['order_created' => true]; }); // Основной спан $mainSpan = $customSpanService->createSpan('process-order-complete', function () { return ['order_processed' => true]; }, [$validationSpan, $inventorySpan, $orderSpan]); $customSpanService->addSpan($mainSpan); } }
Мониторинг и отладка
После настройки синхронизации данные будут доступны в веб‑интерфейсе Zipkin:
-
Откройте Zipkin UI (обычно http://localhost:9411)
-
Выберите сервис из выпадающего списка
-
Настройте временной диапазон
-
Просматривайте трейсы и спаны
В Zipkin вы сможете увидеть:
-
Время выполнения каждого спана
-
Зависимости между сервисами
-
Узкие места в производительности
-
Ошибки и исключения
-
SQL-запросы с временем выполнения
Типичные сценарии отладки
-
Медленные запросы: Анализ времени выполнения SQL-запросов
-
Ошибки внешних API: Просмотр HTTP-клиент запросов
-
Проблемы бизнес-логики: Анализ пользовательских спанов
-
Проблемы производительности: Выявление узких мест в цепочке запросов
Итоги
Laravel Zipkin Tracer вам подойдет если вам нужно:
-
У вас Laravel‑приложение
-
Используется Zipkin как система трейсинга
-
Простоту интеграции с минимальными изменениями в коде (не нужно устанавливать дополнительные расширения)
-
Автоматический трейсинг типичных сценариев
-
Гибкость для создания пользовательских спанов
-
Производительность с асинхронной отправкой данных
❌ Не рекомендуется, если:
-
Нужна поддержка множественных систем трейсинга
-
Требуется полная совместимость с OpenTelemetry
-
Необходимы продвинутые возможности метрик
-
Планируется миграция на другие системы мониторинга
Альтернативы
Для более сложных сценариев рассмотрите:
-
OpenTelemetry PHP — универсальный стандарт
-
Jaeger — альтернативная система трейсинга
-
DataDog APM — коммерческое решение с расширенными возможностями
ссылка на оригинал статьи https://habr.com/ru/articles/920870/
Добавить комментарий