1. Conceptos básicos
  2. Registro

Únete a nuestra comunidad de Telegram @webblend!

Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.

Introducción

Para ayudarte a aprender más sobre lo que sucede dentro de tu aplicación, Laravel proporciona servicios de registro robustos que te permiten registrar mensajes en archivos, en el registro de errores del sistema e incluso en Slack para notificar a todo tu equipo.

El registro de Laravel se basa en "canales". Cada canal representa una forma específica de escribir información de registro. Por ejemplo, el canal single escribe archivos de registro en un solo archivo de registro, mientras que el canal slack envía mensajes de registro a Slack. Los mensajes de registro pueden escribirse en varios canales según su gravedad.

Bajo el capó, Laravel utiliza la biblioteca Monolog, que proporciona soporte para una variedad de controladores de registro poderosos. Laravel facilita la configuración de estos controladores, lo que te permite combinarlos y personalizar el manejo de registros de tu aplicación.

Configuración

Todas las opciones de configuración del comportamiento de registro de tu aplicación se encuentran en el archivo de configuración config/logging.php. Este archivo te permite configurar los canales de registro de tu aplicación, así que asegúrate de revisar cada uno de los canales disponibles y sus opciones. Revisaremos algunas opciones comunes a continuación.

De forma predeterminada, Laravel utilizará el canal stack al registrar mensajes. El canal stack se utiliza para agregar múltiples canales de registro en un solo canal. Para obtener más información sobre la creación de stacks, consulta la documentación a continuación.

Configurar el Nombre del Canal

De forma predeterminada, Monolog se instancia con un "nombre de canal" que coincide con el entorno actual, como production o local. Para cambiar este valor, agrega una opción name a la configuración de tu canal:

'stack' => [
'driver' => 'stack',
'name' => 'channel-name',
'channels' => ['single', 'slack'],
],

Controladores de Canal Disponibles

Cada canal de registro está impulsado por un "controlador" (driver). El controlador determina cómo y dónde se registra realmente el mensaje de registro. Los siguientes controladores de canal de registro están disponibles en cada aplicación Laravel. Ya hay una entrada para la mayoría de estos controladores en el archivo de configuración config/logging.php de tu aplicación, así que asegúrate de revisar este archivo para familiarizarte con su contenido:

Nombre Descripción
custom Un controlador que llama a una fábrica especificada para crear un canal
daily Un controlador Monolog basado en RotatingFileHandler que rota diariamente
errorlog Un controlador Monolog basado en ErrorLogHandler
monolog Un controlador de fábrica Monolog que puede usar cualquier manejador Monolog compatible
papertrail Un controlador Monolog basado en SyslogUdpHandler
single Un canal de registro basado en un solo archivo o ruta (StreamHandler)
slack Un controlador Monolog basado en SlackWebhookHandler
stack Un envoltorio para facilitar la creación de canales "multicanal"
syslog Un controlador Monolog basado en SyslogHandler

Nota Consulta la documentación sobre personalización avanzada de canales para obtener más información sobre los controladores monolog y custom.

Requisitos Previos del Canal

Configurar los Canales Single y Daily

Los canales single y daily tienen tres opciones de configuración opcionales: bubble, permission y locking.

Nombre Descripción Predeterminado
bubble Indica si los mensajes deben propagarse a otros canales después de ser manejados true
locking Intenta bloquear el archivo de registro antes de escribir en él false
permission Los permisos del archivo de registro 0644

Además, la política de retención para el canal daily se puede configurar mediante la opción days:

Nombre Descripción Predeterminado
days El número de días que se deben retener los archivos de registro diarios 7

Configurar el Canal Papertrail

El canal papertrail requiere las opciones de configuración host y port. Puedes obtener estos valores desde Papertrail.

Configurar el Canal Slack

El canal slack requiere una opción de configuración url. Esta URL debe coincidir con una URL para un webhook entrante que hayas configurado para tu equipo de Slack.

Por defecto, Slack solo recibirá registros en el nivel critical y superior; sin embargo, puedes ajustar esto en tu archivo de configuración config/logging.php modificando la opción de configuración level dentro del array de configuración de tu canal de registro de Slack.

Registro de Advertencias de Obsolescencia

PHP, Laravel y otras bibliotecas a menudo notifican a sus usuarios que algunas de sus funciones han sido declaradas obsoletas y se eliminarán en una versión futura. Si deseas registrar estas advertencias de obsolescencia, puedes especificar tu canal de registro preferido deprecations en el archivo de configuración config/logging.php de tu aplicación:

'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
 
'channels' => [
...
]

O puedes definir un canal de registro llamado deprecations. Si existe un canal de registro con este nombre, siempre se usará para registrar obsolescencias:

'channels' => [
'deprecations' => [
'driver' => 'single',
'path' => storage_path('logs/php-deprecation-warnings.log'),
],
],

Construir Pilas de Registro

Como se mencionó anteriormente, el controlador stack te permite combinar varios canales en un solo canal de registro por conveniencia. Para ilustrar cómo usar los stacks de registro, echemos un vistazo a una configuración de ejemplo que podrías ver en una aplicación en producción:

'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['syslog', 'slack'],
],
 
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
 
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'critical',
],
],

Desglosemos esta configuración. Primero, observa que nuestro canal stack agrega dos canales adicionales mediante su opción channels: syslog y slack. Por lo tanto, al registrar mensajes, ambos de estos canales tendrán la oportunidad de registrar el mensaje. Sin embargo, como veremos a continuación, si estos canales realmente registran el mensaje puede depender de la gravedad o "nivel" del mensaje.

Niveles de Registro

Observa la opción de configuración level presente en las configuraciones de canal syslog y slack en el ejemplo anterior. Esta opción determina el "nivel" mínimo que debe tener un mensaje para ser registrado por el canal. Monolog, que impulsa los servicios de registro de Laravel, ofrece todos los niveles de registro definidos en la especificación RFC 5424. En orden descendente de gravedad, estos niveles de registro son: emergency, alert, critical, error, warning, notice, info y debug.

Entonces, imagina que registramos un mensaje usando el método debug:

Log::debug('An informational message.');

Dada nuestra configuración, el canal syslog escribirá el mensaje en el registro del sistema; sin embargo, como el mensaje de error no es critical o superior, no se enviará a Slack. Sin embargo, si registramos un mensaje emergency, se enviará tanto al registro del sistema como a Slack, ya que el nivel emergency está por encima de nuestro umbral mínimo de nivel para ambos canales:

Log::emergency('The system is down!');

Escribir Mensajes de Registro

Puedes escribir información en los registros utilizando el fachada Log. Como se mencionó anteriormente, el registrador proporciona los ocho niveles de registro definidos en la especificación RFC 5424: emergency, alert, critical, error, warning, notice, info y debug:

use Illuminate\Support\Facades\Log;
 
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);

Puedes llamar a cualquiera de estos métodos para registrar un mensaje para el nivel correspondiente. Por defecto, el mensaje se escribirá en el canal de registro predeterminado configurado en tu archivo de configuración logging:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
 
class UserController extends Controller
{
/**
* Muestra el perfil del usuario proporcionado.
*/
public function show(string $id): View
{
Log::info('Showing the user profile for user: {id}', ['id' => $id]);
 
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}

Información Contextual

Se puede pasar un array de datos contextuales a los métodos de registro. Estos datos contextuales se formatearán y mostrarán con el mensaje de registro:

use Illuminate\Support\Facades\Log;
 
Log::info('User {id} failed to login.', ['id' => $user->id]);

Ocasionalmente, es posible que desees especificar alguna información contextual que deba incluirse con todas las entradas de registro posteriores en un canal específico. Por ejemplo, es posible que desees registrar un ID de solicitud asociado con cada solicitud entrante a tu aplicación. Para lograr esto, puedes llamar al método withContext de la fachada Log:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
 
class AssignRequestId
{
/**
* Maneja una solicitud entrante.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
 
Log::withContext([
'request-id' => $requestId
]);
 
$response = $next($request);
 
$response->headers->set('Request-Id', $requestId);
 
return $response;
}
}

Si deseas compartir información contextual en todos los canales de registro, puedes llamar al método Log::shareContext(). Este método proporcionará la información contextual a todos los canales creados y a cualquier canal que se cree posteriormente. Normalmente, el método shareContext debería llamarse desde el método boot de un proveedor de servicios de la aplicación:

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
 
class AppServiceProvider
{
/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Log::shareContext([
'invocation-id' => (string) Str::uuid(),
]);
}
}

Escribir en Canales Específicos

A veces, es posible que desees registrar un mensaje en un canal que no sea el canal predeterminado de tu aplicación. Puedes usar el método channel de la fachada Log para recuperar y registrar en cualquier canal definido en tu archivo de configuración:

use Illuminate\Support\Facades\Log;
 
Log::channel('slack')->info('Something happened!');

Si deseas crear un stack de registro a pedido que consista en varios canales, puedes usar el método stack:

Log::stack(['single', 'slack'])->info('Something happened!');

Canales a Pedido

También es posible crear un canal a pedido proporcionando la configuración en tiempo de ejecución sin que esta configuración esté presente en el archivo de configuración logging de tu aplicación. Para lograr esto, puedes pasar un array de configuración al método build de la fachada Log:

use Illuminate\Support\Facades\Log;
 
Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
])->info('Something happened!');

También puedes desear incluir un canal a pedido en un stack de registro a pedido. Esto se puede lograr incluyendo tu instancia de canal a pedido en el array pasado al método stack:

use Illuminate\Support\Facades\Log;
 
$channel = Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
]);
 
Log::stack(['slack', $channel])->info('Something happened!');

Personalización del Canal Monolog

Personalizar Monolog para Canales

En ocasiones, es posible que necesites un control completo sobre cómo se configura Monolog para un canal existente. Por ejemplo, es posible que desees configurar una implementación personalizada de FormatterInterface de Monolog para el canal incorporado single de Laravel.

Para empezar, define un array tap en la configuración del canal. El array tap debe contener una lista de clases que deberían tener la oportunidad de personalizar (o "intervenir" en) la instancia de Monolog después de que se crea. No hay una ubicación convencional donde deberían colocarse estas clases, así que tienes libertad para crear un directorio dentro de tu aplicación para contener estas clases:

'single' => [
'driver' => 'single',
'tap' => [App\Logging\CustomizeFormatter::class],
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],

Una vez que hayas configurado la opción tap en tu canal, estás listo para definir la clase que personalizará tu instancia de Monolog. Esta clase solo necesita un método: __invoke, que recibe una instancia de Illuminate\Log\Logger. La instancia de Illuminate\Log\Logger delega todas las llamadas de método a la instancia subyacente de Monolog:

<?php
 
namespace App\Logging;
 
use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;
 
class CustomizeFormatter
{
/**
* Personaliza la instancia del registrador proporcionada.
*/
public function __invoke(Logger $logger): void
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new LineFormatter(
'[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
));
}
}
}

Nota Todas tus clases "tap" son resueltas por el contenedor de servicios, por lo que cualquier dependencia del constructor que requieran se inyectará automáticamente.

Crear Canales de Controladores Monolog

Monolog tiene una variedad de manejadores disponibles y Laravel no incluye un canal incorporado para cada uno. En algunos casos, es posible que desees crear un canal personalizado que sea simplemente una instancia de un manejador Monolog específico que no tiene un controlador de registro Laravel correspondiente. Estos canales se pueden crear fácilmente utilizando el controlador monolog.

Al usar el controlador monolog, la opción de configuración handler se utiliza para especificar qué manejador se instanciará. Opcionalmente, se pueden especificar los parámetros del constructor que el manejador necesita mediante la opción de configuración with:

'logentries' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\SyslogUdpHandler::class,
'with' => [
'host' => 'my.logentries.internal.datahubhost.company.com',
'port' => '10000',
],
],

Formateadores Monolog

Cuando uses el controlador monolog, se utilizará el LineFormatter de Monolog como el formateador predeterminado. Sin embargo, puedes personalizar el tipo de formateador que se pasa al manejador mediante las opciones de configuración formatter y formatter_with:

'browser' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\BrowserConsoleHandler::class,
'formatter' => Monolog\Formatter\HtmlFormatter::class,
'formatter_with' => [
'dateFormat' => 'Y-m-d',
],
],

Si estás utilizando un manejador Monolog que es capaz de proporcionar su propio formateador, puedes establecer el valor de la opción de configuración formatter en default:

'newrelic' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\NewRelicHandler::class,
'formatter' => 'default',
],

Procesadores de Monolog

Monolog también puede procesar mensajes antes de registrarlos. Puedes crear tus propios procesadores o utilizar los procesadores existentes ofrecidos por Monolog.

Si deseas personalizar los procesadores para un controlador monolog, agrega un valor processors a la configuración de tu canal:

'memory' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
'processors' => [
// Sintaxis simple...
Monolog\Processor\MemoryUsageProcessor::class,
 
// Con opciones...
[
'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
'with' => ['removeUsedContextFields' => true],
],
],
],

Crear Canales Personalizados mediante Fábricas

Si deseas definir un canal completamente personalizado en el que tengas control total sobre la instanciación y configuración de Monolog, puedes especificar un tipo de controlador custom en tu archivo de configuración config/logging.php. Tu configuración debe incluir una opción via que contenga el nombre de la clase de fábrica que se invocará para crear la instancia de Monolog:

'channels' => [
'example-custom-channel' => [
'driver' => 'custom',
'via' => App\Logging\CreateCustomLogger::class,
],
],

Una vez que hayas configurado el canal de controlador custom, estás listo para definir la clase que creará tu instancia de Monolog. Esta clase solo necesita un método __invoke que debería devolver la instancia del registrador Monolog. El método recibirá como único argumento el array de configuración de canales:

<?php
 
namespace App\Logging;
 
use Monolog\Logger;
 
class CreateCustomLogger
{
/**
* Crea una instancia personalizada de Monolog.
*/
public function __invoke(array $config): Logger
{
return new Logger(/* ... */);
}
}

Seguir Mensajes de Registro con Pail

A menudo, es posible que necesites seguir los registros de tu aplicación en tiempo real. Por ejemplo, al depurar un problema o al monitorear los registros de tu aplicación en busca de tipos específicos de errores.

Laravel Pail es un paquete que te permite sumergirte fácilmente en los archivos de registro de tu aplicación Laravel directamente desde la línea de comandos. A diferencia del comando estándar tail, Pail está diseñado para funcionar con cualquier controlador de registro, incluidos Sentry o Flare. Además, Pail proporciona un conjunto de filtros útiles para ayudarte a encontrar rápidamente lo que estás buscando.

<img src="https://laravel-docs.com/images/docs/10.x/pail-example.png">

Instalación

Advertencia Laravel Pail requiere PHP 8.2+ y la extensión PCNTL.

Para comenzar, instala Pail en tu proyecto utilizando el gestor de paquetes Composer:

composer require laravel/pail

Uso

Para comenzar a seguir los registros, ejecuta el comando pail:

php artisan pail

Para aumentar la verbosidad de la salida y evitar la truncación (...), usa la opción -v:

php artisan pail -v

Para obtener la máxima verbosidad y mostrar trazas de excepciones, usa la opción -vv:

php artisan pail -vv

Para dejar de seguir los registros, presiona Ctrl+C en cualquier momento.

Filtrar Registros

--filter

Puedes usar la opción --filter para filtrar los registros por su tipo, archivo, mensaje y contenido de la traza de la pila:

php artisan pail --filter="QueryException"

--message

Para filtrar los registros solo por su mensaje, puedes usar la opción --message:

php artisan pail --message="User created"

--level

La opción --level se puede utilizar para filtrar los registros por su nivel de registro:

php artisan pail --level=error

--user

Para mostrar solo los registros que se escribieron mientras un usuario específico estaba autenticado, puedes proporcionar el ID del usuario a la opción --user:

php artisan pail --user=1