Laravel Telescope: Элегантный отладчик для PHP-приложений
1. Что такое Laravel Telescope и зачем он нужен?
Laravel Telescope — это мощный инструмент для отладки и мониторинга Laravel-приложений, разработанный командой Laravel. Он предоставляет разработчикам "инспекторский взгляд" на то, что происходит внутри приложения: от входящих запросов и SQL-запросов до заданий очереди, исключений и логов. Telescope работает как панель управления, которая в реальном времени собирает и отображает всю телеметрию.
Зачем это нужно? В современной веб-разработке приложения становятся всё сложнее: используются очереди, кэширование, внешние API, сложные SQL-запросы. Без инструмента вроде Telescope разработчик вынужден вручную добавлять dd() или Log::debug() в код, что замедляет разработку и не даёт полной картины. Telescope автоматически собирает данные о каждом запросе, показывая время выполнения, количество запросов к БД, использованную память и многое другое. Это превращает отладку из гадания в точную науку.
Ключевое преимущество Telescope — его ненавязчивость. Он работает "из коробки" и не требует изменения кода приложения. Данные хранятся в базе данных (по умолчанию MySQL или SQLite), что позволяет анализировать историю запросов. Telescope особенно полезен при разработке API, работе с очередями и отладке медленных страниц.
2. Установка
Установка Laravel Telescope выполняется через Composer — стандартный менеджер пакетов для PHP. Выполните следующую команду в корне вашего Laravel-проекта:
composer require laravel/telescope --dev
Флаг --dev важен: Telescope предназначен только для локальной разработки и не должен устанавливаться на продакшн-серверах. После установки пакета необходимо опубликовать ассеты (CSS/JS) и конфигурацию:
php artisan telescope:install
Эта команда создаст файл конфигурации config/telescope.php и миграцию базы данных. Затем выполните миграцию, чтобы создать таблицы для хранения данных Telescope:
php artisan migrate
После этого Telescope будет доступен по адресу /telescope вашего приложения. Если вы используете Laravel Sail (Docker), не забудьте перезапустить контейнеры.
3. Быстрый старт — минимальный рабочий пример
После установки Telescope начинает автоматически собирать данные. Вам не нужно писать никакого дополнительного кода. Просто откройте браузер и перейдите по адресу http://your-app.test/telescope.
Вы увидите панель с вкладками: Requests, Commands, Schedule, Jobs, Exceptions, Logs, Dumps, Queries, Models, Mail, Notifications, Cache, Events, Gates.
Чтобы убедиться, что всё работает, выполните простой запрос к любому маршруту вашего приложения. Например, откройте главную страницу. Затем перейдите в Telescope и выберите вкладку Requests. Вы увидите запись о вашем запросе с деталями: метод, URI, статус, длительность, количество SQL-запросов и т.д.
Вот пример того, как вы можете вручную добавить данные в Telescope для отладки:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Laravel\Telescope\Telescope;
class UserController extends Controller
{
public function show($id)
{
// Telescope автоматически запишет этот запрос
$user = User::findOrFail($id);
// Вы можете добавить свою "метку" для отслеживания
Telescope::record('custom-event', [
'user_id' => $user->id,
'action' => 'view_profile'
]);
return view('users.show', compact('user'));
}
}
После выполнения этого кода вы увидите запись на вкладке Dumps или Events в Telescope.
4. Основные методы и классы
Laravel Telescope предоставляет несколько ключевых методов и классов для взаимодействия. Ниже приведены 8 наиболее важных из них.
4.1. Telescope::record()
Сигнатура: public static function record(string $type, array $data): void
Что делает: Записывает произвольное событие в Telescope. Позволяет сохранить любые данные для последующего анализа.
<?php
use Laravel\Telescope\Telescope;
Telescope::record('payment-processed', [
'order_id' => 12345,
'amount' => 99.99,
'currency' => 'USD'
]);
4.2. Telescope::tag()
Сигнатура: public static function tag(string|array $tags): void
Что делает: Добавляет теги к текущему запросу. Теги помогают фильтровать и группировать записи в Telescope.
<?php
use Laravel\Telescope\Telescope;
// В контроллере или middleware
Telescope::tag(['slow-request', 'user-account']);
4.3. Telescope::incomingRequest()
Сигнатура: public static function incomingRequest(Illuminate\Http\Request $request): void
Что делает: Вручную регистрирует входящий запрос. Обычно вызывается автоматически, но может быть полезен для кастомной обработки.
<?php
use Laravel\Telescope\Telescope;
use Illuminate\Http\Request;
Route::get('/custom-log', function (Request $request) {
Telescope::incomingRequest($request);
return 'Logged!';
});
4.4. Telescope::recordQuery()
Сигнатура: public static function recordQuery(string $sql, array $bindings, float $time): void
Что делает: Записывает выполненный SQL-запрос с привязками и временем выполнения. Полезно для отладки медленных запросов.
<?php
use Laravel\Telescope\Telescope;
use Illuminate\Support\Facades\DB;
DB::listen(function ($query) {
Telescope::recordQuery(
$query->sql,
$query->bindings,
$query->time
);
});
4.5. Telescope::recordException()
Сигнатура: public static function recordException(Throwable $exception): void
Что делает: Записывает исключение в Telescope. Автоматически вызывается глобальным обработчиком ошибок.
<?php
use Laravel\Telescope\Telescope;
try {
// Код, который может выбросить исключение
throw new \Exception('Test exception');
} catch (\Throwable $e) {
Telescope::recordException($e);
}
4.6. Telescope::recordJob()
Сигнатура: public static function recordJob(string $job, array $payload, string $status, ?float $time = null): void
Что делает: Записывает информацию о выполненном задании очереди. Позволяет отслеживать статус и время выполнения.
<?php
use Laravel\Telescope\Telescope;
use App\Jobs\ProcessPodcast;
$job = new ProcessPodcast($podcast);
Telescope::recordJob(
get_class($job),
['podcast_id' => $podcast->id],
'queued'
);
4.7. Telescope::recordMail()
Сигнатура: public static function recordMail(Illuminate\Mail\SentMessage $message): void
Что делает: Записывает отправленное письмо. Позволяет просматривать содержимое писем прямо в Telescope.
<?php
use Laravel\Telescope\Telescope;
use Illuminate\Support\Facades\Mail;
Mail::to('user@example.com')->send(new \App\Mail\WelcomeMail());
// Telescope автоматически запишет это письмо
4.8. Telescope::recordCache()
Сигнатура: public static function recordCache(string $key, string $action, ?float $time = null): void
Что делает: Записывает операции с кэшем (get, set, forget). Помогает отслеживать эффективность кэширования.
<?php
use Laravel\Telescope\Telescope;
use Illuminate\Support\Facades\Cache;
$value = Cache::remember('users.active', 3600, function () {
return \App\Models\User::where('active', true)->get();
});
// Telescope автоматически запишет операцию с кэшем
5. Реальный практический пример (150+ строк кода)
Рассмотрим реальный сценарий: у нас есть приложение для обработки заказов. Мы хотим отслеживать весь процесс — от создания заказа до отправки уведомления. Используем Telescope для мониторинга.
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use App\Jobs\ProcessOrder;
use Illuminate\Http\Request;
use Laravel\Telescope\Telescope;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class OrderController extends Controller
{
public function store(Request $request)
{
// Начинаем транзакцию БД
DB::beginTransaction();
try {
// Валидация данных
$validated = $request->validate([
'user_id' => 'required|exists:users,id',
'product_id' => 'required|exists:products,id',
'quantity' => 'required|integer|min:1',
'total' => 'required|numeric|min:0'
]);
// Создаем заказ
$order = Order::create($validated);
// Добавляем тег для группировки
Telescope::tag(['order-creation', 'user-' . $order->user_id]);
// Записываем кастомное событие
Telescope::record('order-created', [
'order_id' => $order->id,
'user_id' => $order->user_id,
'total' => $order->total,
'timestamp' => now()->toIso8601String()
]);
// Отправляем задание в очередь
ProcessOrder::dispatch($order)->onQueue('high');
// Логируем успешное создание
Log::info('Order created successfully', ['order_id' => $order->id]);
// Фиксируем транзакцию
DB::commit();
return response()->json([
'message' => 'Order created',
'order_id' => $order->id
], 201);
} catch (\Exception $e) {
// Откатываем транзакцию
DB::rollBack();
// Записываем исключение в Telescope
Telescope::recordException($e);
// Добавляем тег для ошибок
Telescope::tag(['order-error']);
// Логируем ошибку
Log::error('Order creation failed', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'message' => 'Order creation failed',
'error' => $e->getMessage()
], 500);
}
}
public function show($id)
{
// Используем кэш для ускорения
$order = \Cache::remember("order.{$id}", 3600, function () use ($id) {
return Order::with(['user', 'product'])->findOrFail($id);
});
// Telescope автоматически запишет запрос к БД и кэшу
return response()->json($order);
}
public function process(Order $order)
{
// Симуляция долгой обработки
sleep(2);
// Обновляем статус
$order->update(['status' => 'processed']);
// Отправляем уведомление (Telescope запишет его)
$order->user->notify(new \App\Notifications\OrderProcessed($order));
// Записываем в Telescope
Telescope::record('order-processed', [
'order_id' => $order->id,
'processed_at' => now()
]);
return response()->json(['status' => 'processed']);
}
}
// В файле app/Jobs/ProcessOrder.php
namespace App\Jobs;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Laravel\Telescope\Telescope;
class ProcessOrder implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->order = $order;
}
public function handle()
{
// Telescope автоматически запишет выполнение задания
Telescope::tag(['job-processing', 'order-' . $this->order->id]);
// Симуляция обработки
sleep(1);
// Обновляем статус
$this->order->update(['status' => 'completed']);
Telescope::record('job-completed', [
'order_id' => $this->order->id,
'job_class' => self::class
]);
}
public function failed(\Throwable $exception)
{
Telescope::recordException($exception);
Telescope::tag(['job-failed']);
}
}
После
Также в библиотеке
WebSocket в Node.js: библиотека ws для реального времени
Работа с Excel в Kotlin: библиотеки Apache POI и Apache POI для Kotlin
Работа с изображениями в PHP: resize, crop и оптимизация с GD и Imagick
Redis клиент для Kotlin: Lettuce и Kreds — сравнение и примеры
ORM для C++: сравнение и примеры использования библиотек