> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging

> Aprende a registrar el comportamiento de la aplicación en archivos, Slack y servicios externos usando el sistema de logs de Laravel.

## Qué es el logging

El logging de Laravel se diseña en torno al concepto de **canal**.
Un canal es la unidad de configuración que define adónde y cómo se escriben los logs, y puedes combinar diferentes destinos: archivos, Slack, syslog, etc.

Internamente utiliza la biblioteca [Monolog](https://github.com/Seldaek/monolog), lo que te permite aprovechar una amplia gama de handlers y formatters.

<Info>
  Por defecto se usa el canal `stack`, un canal padre que agrupa varios canales.
</Info>

## Configuración

Toda la configuración de logging está en `config/logging.php`. La variable de entorno `LOG_CHANNEL` selecciona el canal por defecto.

```php theme={null}
// config/logging.php
'default' => env('LOG_CHANNEL', 'stack'),
```

### Drivers de canal disponibles

| Driver     | Descripción                                                   |
| ---------- | ------------------------------------------------------------- |
| `single`   | Escribe todos los logs en un único archivo                    |
| `daily`    | Separa los archivos por día (con rotación)                    |
| `slack`    | Envía mensajes a un Incoming Webhook de Slack                 |
| `stack`    | Canal padre que agrupa varios canales                         |
| `syslog`   | Escribe en el syslog del sistema                              |
| `errorlog` | Escribe en el error log de PHP                                |
| `monolog`  | Especifica directamente un handler de Monolog                 |
| `custom`   | Personaliza completamente el canal mediante una clase factory |

### Niveles de log

Laravel soporta los 8 niveles de log definidos en [RFC 5424](https://tools.ietf.org/html/rfc5424).
Están ordenados de mayor a menor gravedad.

| Nivel       | Ejemplo de uso                                                                             |
| ----------- | ------------------------------------------------------------------------------------------ |
| `emergency` | El sistema entero está inutilizable. Requiere respuesta inmediata                          |
| `alert`     | Estado que requiere intervención humana inmediata (por ejemplo, corte de conexión a la BD) |
| `critical`  | Fallo grave con las funciones principales de la app caídas                                 |
| `error`     | Error en tiempo de ejecución. Suele requerir acción, pero no siempre de forma inmediata    |
| `warning`   | Problema potencial. Uso de APIs deprecadas, datos inesperados, etc.                        |
| `notice`    | Funcionamiento normal, pero información destacable                                         |
| `info`      | Operativa habitual: inicio de sesión, confirmación de pedido, etc.                         |
| `debug`     | Información detallada de depuración durante el desarrollo                                  |

El ajuste `level` del canal es el **nivel mínimo** que se registra.
Por ejemplo, con `level` en `error` solo se escriben los eventos de nivel `error` o superior (`critical`, `alert`, `emergency`).

## Uso básico

### La fachada Log

Con la fachada `Illuminate\Support\Facades\Log` escribes mensajes de cada nivel.

```php theme={null}
use Illuminate\Support\Facades\Log;

Log::emergency('El sistema no está disponible.');
Log::alert('La conexión con la base de datos se ha interrumpido.');
Log::critical('El servicio de pagos no responde.');
Log::error('Ha fallado la actualización de datos del usuario.');
Log::warning('Se ha invocado un método deprecado.');
Log::notice('El archivo de configuración se ha recargado.');
Log::info('El usuario ha iniciado sesión.');
Log::debug('Tiempo de ejecución de la consulta: 42ms');
```

Ejemplo de uso en un controlador.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class UserController extends Controller
{
    public function show(string $id): View
    {
        Log::info('Mostrando el perfil del usuario.', ['user_id' => $id]);

        return view('user.profile', [
            'user' => User::findOrFail($id),
        ]);
    }
}
```

### Función helper log()

Con el helper `log()` puedes escribir sin importar la fachada `Log`.

```php theme={null}
log('Log desde el helper.');

// También puedes indicar nivel y contexto
log('Se ha creado un usuario.', 'info', ['user_id' => $user->id]);
```

### Añadir información de contexto

Si pasas un array de contexto junto con el mensaje, puedes registrar la información relacionada de forma agrupada.

```php theme={null}
Log::info('Fallo de inicio de sesión.', [
    'user_id' => $user->id,
    'ip'      => $request->ip(),
    'reason'  => 'Contraseña incorrecta',
]);
```

#### withContext() — contexto común para todo el canal

Cuando quieras adjuntar información común a todas las entradas de un canal a partir de ese momento, usa `withContext()`.
Es adecuado para datos que quieres incluir en todos los logs, como un ID de petición.

```php theme={null}
Log::withContext(['request-id' => (string) Str::uuid()]);

// A partir de aquí, todos los logs incluyen automáticamente request-id
Log::info('Iniciando el proceso.');
Log::error('Se ha producido un error.');
```

#### shareContext() — contexto común para todos los canales

Mientras que `withContext()` solo afecta al canal en curso, `shareContext()` añade contexto común a todos los canales.

```php theme={null}
Log::shareContext(['app-version' => config('app.version')]);
```

## Configuración de canales

### El canal stack — escribir en varios canales a la vez

Con el canal `stack`, una única llamada de log escribe en varios canales.

```php theme={null}
// config/logging.php
'channels' => [
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['daily', 'slack'],
    ],

    'daily' => [
        'driver' => 'daily',
        'path'   => storage_path('logs/laravel.log'),
        'level'  => env('LOG_LEVEL', 'debug'),
        'days'   => 14,
    ],

    'slack' => [
        'driver'   => 'slack',
        'url'      => env('LOG_SLACK_WEBHOOK_URL'),
        'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
        'emoji'    => env('LOG_SLACK_EMOJI', ':boom:'),
        'level'    => 'critical',
    ],
],
```

Con esta configuración, todos los logs de nivel `debug` o superior se escriben en `daily` (archivo) y solo los de nivel `critical` o superior se envían también a `slack`.

<Tip>
  En producción es recomendable configurar el nivel del canal `slack` en `error` o `critical`.
  Si envías incluso los logs poco importantes, las notificaciones se disparan y las alertas relevantes acaban perdiéndose.
</Tip>

### El canal daily — rotación de logs

El canal `daily` separa los archivos por día y elimina automáticamente los antiguos.

```php theme={null}
'daily' => [
    'driver' => 'daily',
    'path'   => storage_path('logs/laravel.log'),
    'level'  => env('LOG_LEVEL', 'debug'),
    'days'   => env('LOG_DAILY_DAYS', 14), // Conservar 14 días
],
```

<Warning>
  Reducir `days` implica que los logs antiguos se eliminan antes.
  Asegura un periodo de retención suficiente para poder investigar incidencias en producción.
</Warning>

### Notificaciones de errores a Slack

Obtén una [URL de Incoming Webhook](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks) de Slack y configúrala en `.env`.

```ini theme={null}
LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
```

```php theme={null}
// config/logging.php
'slack' => [
    'driver'   => 'slack',
    'url'      => env('LOG_SLACK_WEBHOOK_URL'),
    'username' => 'Laravel Error Bot',
    'emoji'    => ':fire:',
    'level'    => 'error',
],
```

Si incluyes `slack` en el canal `stack` y configuras `LOG_CHANNEL=stack`, recibirás notificaciones automáticamente cuando se produzcan errores.

### Escribir en un canal concreto

Con `Log::channel()` puedes indicar explícitamente el canal de destino.

```php theme={null}
// Escribir solo en el canal slack
Log::channel('slack')->error('El servicio de pagos no responde.');

// Escribir simultáneamente en varios canales
Log::stack(['daily', 'slack'])->critical('Ha fallado la conexión con la base de datos.');
```

## Canales bajo demanda

Con `Log::build()` puedes crear canales personalizados al vuelo sin definirlos en el archivo de configuración.
Es útil para pruebas o para destinos de escritura temporales.

```php theme={null}
use Illuminate\Support\Facades\Log;

$channel = Log::build([
    'driver' => 'single',
    'path'   => storage_path('logs/import-' . now()->format('Ymd') . '.log'),
]);

Log::stack([$channel])->info('Iniciando la importación CSV.');
```

## Casos prácticos

### Añadir un ID de petición con un middleware

Al añadir un mismo ID de petición a todos los logs, resulta fácil seguir el flujo de una petición concreta.

<Steps>
  <Step title="Crea el middleware">
    ```shell theme={null}
    php artisan make:middleware AssignRequestId
    ```
  </Step>

  <Step title="Implementa el método handle()">
    ```php theme={null}
    <?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
    {
        public function handle(Request $request, Closure $next): Response
        {
            $requestId = (string) Str::uuid();

            Log::withContext(['request-id' => $requestId]);

            $response = $next($request);

            $response->headers->set('X-Request-Id', $requestId);

            return $response;
        }
    }
    ```
  </Step>

  <Step title="Registra el middleware">
    Regístralo como middleware global en `bootstrap/app.php`.

    ```php theme={null}
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(\App\Http\Middleware\AssignRequestId::class);
    })
    ```
  </Step>
</Steps>

Tras esta configuración, todos los logs incluirán automáticamente el campo `request-id`.

```
[2026-03-01 12:00:00] local.INFO: El usuario ha iniciado sesión. {"request-id":"550e8400-...","user_id":1}
[2026-03-01 12:00:00] local.INFO: Mostrando el dashboard. {"request-id":"550e8400-..."}
```

### Registrar avisos de deprecación

Puedes registrar en el log los avisos cuando se usan funcionalidades deprecadas de PHP o Laravel.

```php theme={null}
// config/logging.php
'deprecations' => [
    'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
    'trace'   => env('LOG_DEPRECATIONS_TRACE', false),
],
```

Indica el canal en `.env`.

```ini theme={null}
LOG_DEPRECATIONS_CHANNEL=daily
```

## Laravel Pail — monitorización de logs en tiempo real

[Laravel Pail](https://github.com/laravel/pail) es una herramienta de desarrollo que permite ver los logs de la aplicación en tiempo real desde la terminal. A diferencia del `tail` estándar, está diseñada para funcionar con cualquier driver de log, incluidos [Laravel Nightwatch](https://nightwatch.laravel.com), Sentry y Flare.

<Info>
  Para ejecutar Pail necesitas la extensión [PCNTL](https://www.php.net/manual/es/book.pcntl.php) de PHP.
</Info>

### Instalación

```shell theme={null}
composer require --dev laravel/pail
```

### Uso básico

```shell theme={null}
# Ver los logs en streaming
php artisan pail

# Vista detallada (sin truncar)
php artisan pail -v

# Muestra también el stack trace
php artisan pail -vv
```

### Filtrar logs

```shell theme={null}
# Filtrar por palabra clave
php artisan pail --filter="QueryException"

# Filtrar solo por mensaje
php artisan pail --message="inicio de sesión"

# Filtrar por nivel de log
php artisan pail --level=error

# Ver solo los logs de un usuario concreto
php artisan pail --user=1
```

## Resumen

<AccordionGroup>
  <Accordion title="Cómo elegir el nivel de log">
    | Nivel       | Cuándo usarlo                                                                       |
    | ----------- | ----------------------------------------------------------------------------------- |
    | `emergency` | Fallo catastrófico que deja el sistema inoperativo                                  |
    | `alert`     | Estado que exige intervención humana inmediata                                      |
    | `critical`  | Fallo grave en el que las funciones principales no funcionan                        |
    | `error`     | Error en runtime inesperado que requiere acción                                     |
    | `warning`   | Estados a los que hay que prestar atención, como uso deprecado o datos inesperados  |
    | `notice`    | Operativa normal pero digna de registrar                                            |
    | `info`      | Registro de acciones de usuario o eventos de negocio                                |
    | `debug`     | Información detallada de depuración durante desarrollo (no necesaria en producción) |
  </Accordion>

  <Accordion title="Guía para elegir canal">
    * **Entorno de desarrollo**: escribir a archivo con `single` o `daily`.
    * **Producción**: `stack` combinando `daily` (guardado en archivo) y `slack` (notificaciones de error).
    * **Logs de procesos específicos**: crear canales bajo demanda con `Log::build()` para escribir en archivos separados.
    * **Monitorización en tiempo real**: verificar desde la terminal con `php artisan pail`.
  </Accordion>

  <Accordion title="Precauciones en producción">
    * Los logs `debug` pueden contener información sensible. En producción se recomienda `LOG_LEVEL=error` o superior.
    * Rota periódicamente los archivos de log para no ocupar el disco (opción `days` del canal `daily`).
    * Ten en cuenta los rate limits de servicios externos como Slack. Ajusta el nivel para que solo se notifiquen los errores importantes.
  </Accordion>
</AccordionGroup>


## Related topics

- [Manejo de errores](/es/error-handling.md)
- [Introducción a Laravel Nightwatch](/es/blog/nightwatch-introduction.md)
- [Laravel Pulse](/es/pulse.md)
- [Trait Conditionable](/es/advanced/conditionable.md)
- [Actualización de Laravel 9 a 10](/es/blog/upgrade-9-to-10.md)
