Logging
Logging
Introduction
Para ayudarte a aprender más acerca de lo que está sucediendo dentro de tu aplicación, Laravel proporciona servicios de registro robustos que le permiten registrar mensajes en archivos, el error log del sistema, e incluso a Slack para notificar a todo su equipo.
Laravel logging esta basado en “channels”. Cada channel representa una forma específica de escribir información de log. Por ejemplo, el canal single escribe logs en un único archivo de registro, mientras que el channel slack envía mensajes de registro a Slack. Los mensajes de logs pueden escribirse en varios canales en función de su gravedad.
Bajo el capó, Laravel utiliza la biblioteca Monolog, que proporciona soporte para una variedad de potentes handlers de logs. Laravel hace que sea muy fácil configurar estos gestores, lo que te permite mezclarlos y combinarlos para personalizar el manejo de registros de tu aplicación.
Configuration
Todas las opciones de configuración que controlan el logging de tu aplicación se encuentran en el archivo de configuración config/logging.php. Este archivo le permite configurar los canales de logs de tu aplicación, así que asegúrese de revisar cada uno de los canales disponibles y sus opciones.
Por defecto, Laravel utilizará el canal stack cuando muestres logs. El canal de 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 pilas, consulte la documentación siguiente. (visto mas abajo: Building Stacks)
Available Channel Drivers
Cada canal de log funciona con un “driver”. El driver determina cómo y dónde se registra realmente el mensaje de log. Los siguientes channel drivers están disponibles en todas las aplicaciones Laravel. Una muestra para la mayoría de estos drivers ya está presente 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:
| Name | Description |
|---|---|
custom |
A driver that calls a specified factory to create a channel. |
daily |
A RotatingFileHandler based Monolog driver which rotates daily. |
errorlog |
An ErrorLogHandler based Monolog driver. |
monolog |
A Monolog factory driver that may use any supported Monolog handler. |
papertrail |
A SyslogUdpHandler based Monolog driver. |
single |
A single file or path based logger channel (StreamHandler). |
slack |
A SlackWebhookHandler based Monolog driver. |
stack |
A wrapper to facilitate creating “multi-channel” channels. |
syslog |
A SyslogHandler based Monolog driver. |
Consulta la documentación sobre personalización avanzada de canales para saber más sobre el monolog y los drivers custom.
Configuring the Channel Name
Por defecto, Monolog se instancia con un “nombre de canal” que coincide con el entorno actual, como producction o local. Para cambiar esto, puede añadir una opción de name a la configuración de su channel:
'stack' => [
'driver' => 'stack',
'name' => 'channel-name',
'channels' => ['single', 'slack'],
],
Channel Prerequisites
Configuring the Single and Daily Channels
El canal de single y daily channels tienen tres opciones de configuración: bubble, permission, y locking.
| Name | Description | Default |
|---|---|---|
bubble |
Indica si los mensajes deben pasar a otros canales después de ser gestionados. | true |
locking |
Intenta bloquear el archivo de registro antes de escribir en él. | false |
permission |
Los permisos del archivo de log | 0644 |
Además, la política de retención (policy retention) del canal daily puede configurarse mediante la variable de entorno LOG_DAILY_DAYS o estableciendo la opción de configuración days.
| Name | Description | Default |
|---|---|---|
days |
The number of days that daily log files should be retained. | 14 |
Configuring the Papertrail Channel
El channel papertrail requiere opciones de configuración de host y port. Éstas pueden definirse mediante las variables de entorno PAPERTRAIL_URL y PAPERTRAIL_PORT. Puede obtener estos valores de Papertrail
Configuring the Slack Channel
El channel slack requiere una opción de configuración url. Este valor puede definirse mediante la variable de entorno LOG_SLACK_WEBHOOK_URL. Esta URL debe coincidir con la URL de un webhook entrante que haya configurado para su equipo de Slack.
Por defecto, Slack sólo recibirá registros de nivel critical y superior; sin embargo, puede ajustar esto utilizando la variable de entorno LOG_LEVEL o modificando la opción de configuración de level dentro del array de configuración de Slack log channel
Logging Deprecation Warnings
PHP, Laravel, y otras librerías a menudo notifican a sus usuarios que algunas de sus características han quedado obsoletas y serán eliminadas en una versión futura. Si desea registrar estas advertencias de deprecated, puede especificar su canal de registro de deprecated preferido usando la variable de entorno LOG_DEPRECATIONS_CHANNEL, o dentro del archivo de configuración config/logging.php de tu aplicación:
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
'channels' => [
// ...
]
También puede definir un channel de logs llamado deprecations. Si existe un channel de logs con este nombre, siempre se utilizará para registrar las deprecations:
'channels' => [
'deprecations' => [
'driver' => 'single',
'path' => storage_path('logs/php-deprecation-warnings.log'),
],
],
Building Log Stacks
Como se ha mencionado anteriormente, el driver de stack permite combinar varios canales en un único channel de logs para mayor comodidad. Para ilustrar cómo usar las stacks logs, veamos un ejemplo de configuración que podrías ver en una aplicación de producción:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['syslog', 'slack'],
'ignore_exceptions' => false,
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
],
Vamos a diseccionar esta configuración. En primer lugar, observa que nuestro channe stack agrega otros dos canales a través de la opción channels: syslog y slack. Así, cuando se registran mensajes, ambos canales tendrán la oportunidad de registrar el mensaje. Sin embargo, como veremos más adelante, el que estos canales registren realmente el mensaje puede estar determinado por la gravedad / “nivel” del mensaje.
Log Levels
Tenga en cuenta la opción de configuración de level presente en las configuraciones de los channels p**syslog** y slack del ejemplo anterior. Esta opción determina el “nivel” mínimo que debe tener un mensaje para ser registrado por el channel. Monolog, que sustenta los servicios de logging 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.
Log::debug('An informational message.');
Dada nuestra configuración, el channel syslog escribirá el mensaje en el log del sistema; sin embargo, dado que el mensaje de error no es critical o superior, no se enviará a Slack. Sin embargo, si registramos un mensaje de emergency, se enviará tanto al log del sistema como a Slack, ya que el nivel de emergency está por encima de nuestro umbral de nivel mínimo para ambos canales:
Log::debug('An informational message.');
Writing Log Messages
Puede escribir información en los logs utilizando la facade Log. Como se mencionó anteriormente, el logger 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);
Puede llamar a cualquiera de estos métodos usando la facade para registrar un mensaje en cualquier nivel. El mensaje se escribirá en el channel de logs predeterminado configurado en el archivo logging de config.
<?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
{
/**
* Show the profile for the given user.
*/
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)
]);
}
}
Contextual Information
Se puede pasar un array con datos contextuales a los métodos de log. Estos datos contextuales se formatearán y mostrarán con el mensaje del log:
use Illuminate\Support\Facades\Log;
Log::info('User {id} failed to login.', ['id' => $user->id]);
Ocasionalmente, puede que desees especificar alguna información contextual que debería incluirse en las subsiguientes mensajes de logs en un channel en particular. Por ejemplo, es posible que desee registrar un ID de request que esté asociado con cada solicitud entrante a tu aplicación. Para ello, puede llamar al método withContext de la facade Log:
Esto significa que cualquier llamada posterior a Log::info(), Log::error(), o cualquier otro método de log en la misma solicitud, incluirá automáticamente este request-id.
<?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
{
/**
* Handle an incoming request.
*
* @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 desea compartir información contextual a través de todos los canales de registro, puede invocar el 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:
<?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
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$requestId = (string) Str::uuid();
Log::shareContext([
'request-id' => $requestId
]);
// ...
}
}
ℹ️ Si necesita compartir el contexto de logs mientras procesa queued jobs, puede utilizar job middleware.
Writing to Specific Channels
A veces es posible que desees registrar un mensaje en un canal distinto del canal por defecto de tu aplicación. Puede utilizar el método channel de la facade Log para recuperar y registrar en cualquier canal definido en tu archivo de config:
use Illuminate\Support\Facades\Log;
Log::channel('slack')->info('Something happened!');
Si desea crear un stack de varios canales, puedes utilizar el método stack:
Log::stack(['single', 'slack'])->info('Something happened!');
On-Demand Channels
También es posible crear un canal bajo demanda proporcionando la configuración en tiempo de ejecución sin que dicha configuración esté presente en el fichero de configuración de logging de tu aplicación. Para ello, puedes pasar un array de configuración al método de build de la facade Log:
use Illuminate\Support\Facades\Log;
Log::build([
'driver' => 'single',
'path' => storage_path('logs/custom.log'),
])->info('Something happened!');
También puedes incluir un canal creado en una stack. Esto se puede lograr incluyendo la instancia del channel dentro del array del 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!');
Monolog Channel Customization
Customizing Monolog for Channels
A veces es posible que necesite un control completo sobre cómo Monolog está configurado para un canal existente. Por ejemplo, es posible que desee configurar una implementación personalizada de Monolog FormatterInterface para el canal single incorporado de Laravel.
Para empezar, define un array tap en la configuración del canal. El array tap debe contener una lista de clases que deben tener la oportunidad de personalizar la instancia Monolog después de su creación. No hay una ubicación convencional donde estas clases deben ser colocados, por lo que eres libres de crear un directorio dentro de su aplicación para contener estas clases:
'single' => [
'driver' => 'single',
'tap' => [App\Logging\CustomizeFormatter::class],
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
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 sólo necesita un único método: __invoke, que recibe una instancia Illuminate\Log\Logger. La instancia Illuminate\Log\Logger realiza un proxy a todas las llamadas de métodos bajo la instancia Monolog:
<?php
namespace App\Logging;
use Illuminate\Log\Logger;
use Monolog\Formatter\LineFormatter;
class CustomizeFormatter
{
/**
* Customize the given logger instance.
*/
public function __invoke(Logger $logger): void
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new LineFormatter(
'[%datetime%] %channel%.%level_name%: %message% %context% %extra%'
));
}
}
}
ℹ️ ℹ️ Todas sus clases “tap” son resueltas por el contenedor de servicios, por lo que cualquier dependencia del constructor que requieran será automáticamente inyectada.
Creating Monolog Handler Channels
Monolog tiene una variedad de handlers disponibles y Laravel no incluye un canal incorporado para cada uno. En algunos casos, es posible que desee crear un canal personalizado que no es más que una instancia de un handler de Monolog que no tiene un driver de log de Laravel correspondiente. Estos canales se pueden crear fácilmente utilizando el driver monolog.
Cuando se utiliza el driver monolog, la opción de configuración del handler se utiliza para especificar qué handler se instanciará. Opcionalmente, cualquier parámetro al constructor que el handler necesite puede ser especificado usando 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',
],
],
Monolog Formatters
Cuando se utiliza el driver monolog, el Monolog LineFormatter se utilizará como el formatter por defecto. Sin embargo, puedes personalizar el tipo de formatter pasado al handler utilizando 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 utiliza un Monolog handler capaz de proporcionar su propio formatter, puede establecer el valor de la opción de formatter en default
'newrelic' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\NewRelicHandler::class,
'formatter' => 'default',
],
Monolog Processors
Monolog también puede procesar mensajes antes de registrarlos. Puede crear tus propios procesadores o utilizar los procesadores existentes que ofrece Monolog.
Si desea personalizar los procesadores para un driver de monolog, añade un valor de configuración processors
'memory' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
'processors' => [
// Simple syntax...
Monolog\Processor\MemoryUsageProcessor::class,
// With options...
[
'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
'with' => ['removeUsedContextFields' => true],
],
],
],
Creating Custom Channels via Factories
Si desea definir un canal totalmente personalizado en el que usted tiene el control total sobre la instanciación y configuración de Monolog, puede especificar un tipo de driver custom en su archivo de configuración config/logging.php. Su configuración debe incluir una opción via que contenga el nombre de la clase de factory que será invocada para crear la instancia de Monolog:
'channels' => [
'example-custom-channel' => [
'driver' => 'custom',
'via' => App\Logging\CreateCustomLogger::class,
],
],
Una vez que hayas configurado el canal del driver custom, estás listo para definir la clase que creará tu instancia Monolog. Esta clase sólo necesita un único método __invoke que debe devolver la instancia del logger Monolog. El método recibirá el array de canales de config como único argumento:
<?php
namespace App\Logging;
use Monolog\Logger;
class CreateCustomLogger
{
/**
* Create a custom Monolog instance.
*/
public function __invoke(array $config): Logger
{
return new Logger(/* ... */);
}
}
Tailing Log Messages Using Pail
A menudo puede que necesites seguir los registros de tu aplicación en tiempo real. Por ejemplo, al depurar un problema o al supervisar los registros de su aplicación en busca errores
Laravel Pail es un paquete que le permite navegar fácilmente en los archivos de registro de su aplicación Laravel directamente desde la línea de comandos. A diferencia del comando tail estándar, Pail está diseñado para trabajar con cualquier log driver, incluyendo Sentry o Flare. Además, Pail proporciona un conjunto de filtros útiles para ayudarte a encontrar rápidamente lo que buscas.
More info of Pail in : https://laravel.com/docs/11.x/logging#tailing-log-messages-using-pail