Monitorizando una Aplicación Laravel con Telescope: Un Ejemplo Práctico Paso a Paso
Depurar y optimizar el rendimiento de aplicaciones Laravel puede ser todo un desafío sin las herramientas adecuadas. Afortunadamente, Laravel incluye Telescope, una fantástica herramienta para monitorear y analizar apps al detalle.
Índice
Preparando el Entorno de Desarrollo con Laravel
Necesitamos tener una aplicación Laravel para utilizar Telescope. Podemos crear una rápidamente con:
Instalando Laravel vía Composer
Primero instalamos Laravel usando Composer:
composer create-project laravel/laravel telescope-test
Esto creará una carpeta telescope-test
con una instalación limpia de Laravel.
Configurando el Servidor de Desarrollo
Luego iniciamos el servidor incorporado con:
cd telescope-test
php artisan serve
Esto levantará el servidor en http://localhost:8000
. Accedamos para verificar que funcione.
Creando una Aplicación de Ejemplo
Ahora, necesitamos una aplicación para monitorizar. Vamos a crear un simple gestor de tareas con capacidad para:
- Listar tareas
- Crear una nueva tarea
- Marcar tareas como completadas
Primero, la migración:
php artisan make:migration create_tasks_table
// migrations/create_tasks_table.php
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('completed')->default(false);
$table->timestamps();
});
php artisan migrate
Ten en cuenta que debes configurar el .env
para ejecutar las migraciones como en cualquier otro proyecto laravel
Después seguimos con el modelo
php artisan make:model Task
// app/Models/Task.php
class Task extends Model
{
use HasFactory;
protected $fillable = [
'name',
'completed'
];
}
Luego, el controlador con las operaciones CRUD:
php artisan make:controller TaskController
<?php
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Http\Request;
class TaskController extends Controller
{
public function index()
{
$tareas = Task::orderBy('id', 'desc')->get()->all();
return view('tareas', [
'tareas' => $tareas
]);
}
public function edit($id)
{
$tarea = Task::find($id);
return view('tarea', [
'tarea' => $tarea
]);
}
public function store(Request $request)
{
Task::create($request->all());
return redirect()->to(route('listar-tareas'));
}
public function update(Request $request, $id)
{
$tarea = Task::find($id);
$tarea->completed = $request->completed == 'on' ? 1 : 0;
$tarea->save();
return redirect()->to(route('listar-tareas'));
}
}
Ahora las vistas necesarias, las creamos en resources/views
:
{{-- tareas.blade.php --}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Tareas</title>
</head>
<body>
<form action="{{ route('crear-tarea') }}" method="post">
@csrf
<label for="name">Nombre tarea</label>
<input type="text" id="name" name="name">
<button type="submit">Enviar</button>
</form>
@foreach ($tareas as $tarea)
<p>{{ $tarea->name }} <a href="{{ route('editar-tarea', ['id' => $tarea->id]) }}">Ver Tarea</a></p>
@endforeach
</body>
</html>
{{-- tarea.blade.php --}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Editar Tarea {{ $tarea->name }}</title>
</head>
<body>
<form action="{{ route('actualizar-tarea', ['id' => $tarea->id]) }}" method="POST">
@csrf
@method('PUT')
<label for="name">Nombre tarea</label>
<input type="text" id="name" name="name" value="{{ $tarea->name }}" disabled>
<label for="completed">Estado tarea</label>
<input type="checkbox" name="completed" id="completed" {{$tarea->completed == 1 ? 'checked' : ''}}>
<button type="submit">Enviar</button>
</form>
</body>
</html>
Finalmente, las rutas para acceder a las acciones:
Route::get('/tareas', [TaskController::class, 'index'])->name('listar-tareas');
Route::post('/nueva-tarea', [TaskController::class, 'store'])->name('crear-tarea');
Route::get('/editar-tarea/{id}', [TaskController::class, 'edit'])->name('editar-tarea');
Route::put('/tarea-editada/{id}', [TaskController::class, 'update'])->name('actualizar-tarea');
Además de las migraciones, modelos, controlador y rutas, vamos a crear un seeder para insertar datos de prueba:
php artisan make:seeder TaskSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TaskSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// Borra los registros existentes en la tabla antes de insertar nuevos datos
DB::table('tasks')->truncate();
// Genera 50 registros aleatorios
$tasks = [];
for ($i = 1; $i <= 50; $i++) {
$tasks[] = [
'name' => 'Task ' . $i,
'completed' => rand(0, 1) == 1, // Genera valores aleatorios para 'completed'
'created_at' => now(),
'updated_at' => now(),
];
}
// Inserta los registros en la tabla
DB::table('tasks')->insert($tasks);
}
}
Finalmente, para ejecutar el seeder:
php artisan db:seed --class=TaskSeeder
Habilitando e Instalando Telescope
Telescope viene incluido en Laravel pero debemos instalarlo por separado:
Requisitos Previos y Consideraciones
Antes, debes tener en cuenta que Telescope requiere:
- Laravel >= 5.5.0
- PHP >= 7.1.3
IMPORTANTE: solo se usa en desarrollo ya consume muchos recursos. Todos los datos de Laravel Telescope se almacenarán en la base de datos de nuestra aplicación
Agregando Telescope vía Composer
Instalamos con:
composer require laravel/telescope
composer require laravel/telescope --dev // Si solo lo queremos en nuestro entorno Local
Esto agregará Telescope y sus dependencias al proyecto.
Publicando los Assets y Configurándolos
Luego publicamos los assets:
php artisan telescope:publish
Esto publicará la configuración, assets y migraciones necesarias.
Instalación de Laravel Telescope
Instalamos Laravel Telescope:
php artisan telescope:install
Esto instalara Laravel Telescope
Migración Laravel Telescope
Migramos las tablas de Laravel Telescope:
php artisan migrate
Con esto ya tendríamos configurado Laravel Telescope
Usando Telescope para Depurar la Aplicación
Para acceder a Telescope, navega a http://127.0.0.1:8000/telescope
. Analicemos las principales características para depurar la app:
Visualizando Logs y Queries en Tiempo Real
En Logs vemos los logs generados en tiempo real. Los errores se resaltan en rojo:
En Queries tenemos todas las consultas SQL ejecutadas, con sus tiempos:
Inspeccionando y Filtrando Requests
Cada request se registra para inspeccionarlo después. Podemos filtrar por rutas, tiempos de respuesta, códigos HTTP, etc.
Así, depuramos requests problemáticos fácilmente:
Depurando Excepciones y Errores
Los errores y excepciones se registran con información como la pila de llamadas, variables y sesión del usuario.
Esto facilita replicar y solucionar bugs:
Conclusión
En resumen, Telescope es una poderosa herramienta incluida en Laravel para monitorear y depurar aplicaciones al detalle. Nos permite:
- Identificar rápidamente errores y excepciones
- Inspeccionar y filtrar requests problemáticos
- Optimizar queries lentas y mejorar el rendimiento
- Generar reportes personalizados para análisis avanzado
¡Telescope nos dará una gran visibilidad de lo que sucede en nuestra aplicación para mantenerla optimizada!
Preguntas Frecuentes
No, Telescope sólo debe usarse en entornos de desarrollo. Consumirá muchos recursos del servidor, por lo que no es recomendable en producción.
Telescope almacena todos los logs, queries, requests, errores, excepciones y métricas de rendimiento que ocurren en la aplicación. Pero no almacena ningún dato de sesión, variables de entorno u otro dato sensible.
Sólo es necesario configurar la base de datos donde Telescope almacenará los datos monitorizados. El resto viene listo para usarse luego de instalarlo.
Sí, la configuración permite especificar qué datos se van a almacenar y cuales no. Por ejemplo, se pueden excluir ciertas rutas o queries.
Algunas alternativas populares son Debugbar, Clockwork o Tideways. Telescope tiene la ventaja de estar integrado en Laravel y no requerir configuración adicional.