Cargando…

Esto está tardando más de lo esperado.

Volver al centro de ayuda

Logs y depuración

Dónde se escriben los errores, con qué frecuencia se reportan, cómo recibirlos en Slack, y las herramientas que encuentran páginas lentas y consultas N+1.

El kit escribe un log diario, limita los reportes de una excepción repetida para que una página rota no lo llene, y puede publicar cada error nuevo en Slack. En desarrollo suma la debugbar, un detector de consultas N+1 y un seguimiento en vivo del log. Esta guía cubre las variables detrás de cada uno y las dos cosas que hacer antes de desplegar: proteger el visor de logs y poner el token de Slack.

El visor de logs en /logs

routes/web.php registra GET /logs con el LogViewerController del paquete rap2hpoutre/laravel-log-viewer. Lista los archivos de storage/logs/, te deja leerlos, descargarlos y borrarlos, y el kit no le agrega ningún middleware: la ruta es pública. Protégela antes de desplegar, ya sea envolviéndola:

Route::get('logs', LogViewerController::class . '@index')->middleware(['auth', 'role:admin']);

o moviendo la línea a routes/admin.php, donde se convierte en /admin/logs detrás del rol de administrador.

Canales y variables

config/logging.php conserva los canales de Laravel más uno del kit, slack_api.

Variable Valor por omisión Qué hace
LOG_CHANNEL daily El canal al que se escribe todo. daily rota storage/logs/laravel-YYYY-MM-DD.log
LOG_STACK daily Canales separados por coma que se usan cuando LOG_CHANNEL=stack
LOG_LEVEL debug Nivel mínimo para single, daily, papertrail, stderr, syslog y errorlog; critical para slack
LOG_DAILY_DAYS 14 Días de archivos diarios que se conservan antes de que la rotación los borre
LOG_DEPRECATIONS_CHANNEL null A dónde van los avisos de funciones obsoletas de PHP y librerías; null los descarta
LOG_DEPRECATIONS_TRACE false Incluir la traza con cada aviso de obsolescencia
LOG_STDERR_FORMATTER ninguno Clase de formateador de Monolog para el canal stderr, para contenedores que recogen la salida de error
LOG_SYSLOG_FACILITY LOG_USER Facility del canal syslog
LOG_PAPERTRAIL_HANDLER SyslogUdpHandler Clase del handler del canal papertrail
PAPERTRAIL_URL, PAPERTRAIL_PORT ninguno Host y puerto del canal papertrail
LOG_SLACK_WEBHOOK_URL ninguno Webhook entrante del canal slack estándar de Laravel
LOG_SLACK_USERNAME Laravel Log Nombre con el que publica el canal slack estándar
LOG_SLACK_EMOJI :boom: Icono del canal slack estándar
SLACK_BOT_TOKEN ninguno Token de bot del canal slack_api del kit; definirlo activa las alertas de error de abajo
SLACK_LOG_CHANNEL #errores Canal de Slack al que publica slack_api

El canal slack estándar es un canal normal de Laravel: nada en el kit escribe en él salvo que lo agregues a LOG_STACK. Las alertas de error del kit pasan por slack_api.

Alertas de error en Slack

slack_api es un SlackHandler de Monolog que habla con la API de Slack con un token de bot. Publica como Laravel Logs con el icono :boom:, en nivel error y superiores, como un adjunto que incluye el contexto de la excepción salvo el objeto de la excepción, la URL y el id de usuario.

Para activarlo:

  1. Crea una app de Slack con un token de bot que tenga chat:write, e invita al bot al canal.
  2. Define las variables:
SLACK_BOT_TOKEN=xoxb-tu-token
SLACK_LOG_CHANNEL=#errores

Nada más cambia: el manejador de excepciones en bootstrap/app.php revisa si slack_api tiene token y, cuando lo tiene, publica cada excepción que pasa el límite de abajo. Dos mensajes nunca llegan a Slack ni así, porque son ruido que la siguiente petición arregla: una conexión a la base de datos rechazada, SQLSTATE[HY000] [2002], y el Cannot update locked property de Livewire.

Con qué frecuencia se reporta una excepción

bootstrap/app.php decide, en withExceptions, si una excepción se escribe siquiera. En el entorno local cada excepción se reporta, todas las veces. En los demás:

  • El mensaje se normaliza, reemplazando números y fechas por marcadores, y se convierte en un hash junto con el nombre de la clase. El conteo de esa firma se guarda en caché 30 días.
  • La excepción se reporta cuando el conteo llega a 1, 10, 25, 50, 100, 300, 500 o 1000, y después cada 1000.
  • Incluso en esos conteos, la misma firma se reporta a lo más una vez cada 5 minutos.
  • Una excepción lanzada dentro del componente anfitrión de modales, wire-elements-modal, nunca se reporta.
  • Los mensajes listados en ignoredExceptionMessages(), hoy sólo el activeComponent must not be accessed before initialization del paquete de modales, no se reportan en ningún entorno.

Cada reporte lleva contexto extra: la última URL no Livewire que la persona abrió, la ruta de la petición, el user agent, el entorno, el componente Livewire que corría y cuántas veces se ha visto esta excepción. Ese es el conteo que el botón Limpiar caché de logs de La devzone reinicia, cuando el almacén de caché es database, para que un error corregido se reporte de nuevo desde 1.

El detector de consultas N+1

beyondcode/laravel-query-detector observa cada petición y reporta una relación cargada dentro de un ciclo. config/querydetector.php:

Variable Valor por omisión Qué hace
QUERY_DETECTOR_ENABLED null null sigue a APP_DEBUG; true o false lo fuerza
QUERY_DETECTOR_THRESHOLD 1 Cuántas veces puede correr una relación antes de reportarse; 1 reporta cada repetición
QUERY_DETECTOR_LOG_CHANNEL daily Canal usado cuando se agrega la salida Log

Su salida es la debugbar: los hallazgos aparecen en una pestaña Messages de la barra. Pon en la lista blanca una relación que se carga a propósito en el arreglo except de la configuración, con la clase del modelo y el nombre de la relación:

'except' => [
    App\Models\Order::class => [
        App\Models\OrderLine::class,
        'lines',
    ],
],

La debugbar

barryvdh/laravel-debugbar es una dependencia de desarrollo; muestra consultas, vistas, la sesión y la línea de tiempo de la petición al pie de cada página. config/debugbar.php:

Variable Valor por omisión Qué hace
DEBUGBAR_ENABLED null null sigue a APP_DEBUG; pon false para ocultarla con debug activo
DEBUGBAR_EDITOR phpstorm Editor que abren los enlaces a archivos: phpstorm, vscode, vscode-insiders, vscode-remote, vscode-insiders-remote, vscodium, textmate, emacs, sublime, atom, nova, macvim, idea, netbeans, xdebug o espresso
DEBUGBAR_THEME auto auto, light o dark
DEBUGBAR_OPEN_STORAGE false Permite a cualquiera abrir desde la barra los datos guardados de peticiones anteriores; nunca lo actives donde el sitio es público
DEBUGBAR_LOCAL_SITES_PATH, DEBUGBAR_REMOTE_SITES_PATH vacío Mapean una ruta dentro de un contenedor o VM a la ruta en tu máquina para que los enlaces al editor resuelvan

Nunca la actives en producción: expone consultas y datos de sesión a cualquiera que cargue una página.

Sigue el log mientras desarrollas

composer dev arranca el servidor, el worker de la cola, Vite y php artisan pail, que imprime cada entrada del log en la terminal conforme ocurre. Corre php artisan pail solo para seguir el log de un sitio en marcha, y php artisan pail --filter="QueryException" para ver un solo tipo de entrada. En un servidor, sigue el archivo diario:

tail -f storage/logs/laravel-$(date +%F).log

Las variables que definir en un servidor, estas entre ellas, están listadas en Despliega tu proyecto.