Laravel Telescope для PHP: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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']);
    }
}

После

Рекомендаций