Cómo logear errores con PHP

Por más esfuerzo que pongas, los usuarios se las arreglan para encontrar errores antes que vos.

No sólo eso, lo más probable es que, al reportar un error (o intentar hacerlo), no tengan mucho más para decir que

«No hice nada y el sistema se colgó»

Evidentemente, no es un panorama muy alentador como punto de partida para encontrar una solución, ¿cierto?

Que bueno sería saber exactamente qué estaba pasando en el momento en que se produjo el error…

Precisamente, es ahí donde tener un buen log de errores puede hacer la diferencia entre perder el fin de semana y ser el héroe del día.

Veamos entonces algunas técnicas para contar con esa información cuando se la necesita (y sí… tarde o temprano la vas a necesitar).

La primera opción es casi obvia: guardar los logs mediante tu propio mecanismo (mucho fopen, fwrite o similares, etc…).

Podés hacer esto, y hasta puede funcionar bien, pero representa un esfuerzo importante y una gran propensión a generar más errores que los que previene.

Por ejemplo, hay que tener en cuenta que, si la cantidad de usuarios concurrentes es alta (como se espera en un entorno web) habrá problemas de disponibilidad del archivo donde se almacenan los logs, con lo cual probablemente tengas que implementar tu propio sistema de semáforos o algo así… un poco demasiado para lo que estás queriendo lograr, ¿no?

Ojo, PHP te provee una función bastante interesante: error_log, que ya maneja toda esa complejidad… no está mal, ¿cierto?

Pero podés encontrarte con casos aún más complejos, como ser un sistema distribuido que requiere de logs centralizados.

Un caso típico es cuando se trata de muchos servidores detrás de un balanceador de carga:

En este caso, te interesará que si hay errores en cualquiera de los servidores se tomen como un único error de la aplicación, con lo cual, los archivos de logs individuales de cada servidor tendrán poca relevancia.

Nuevamente, aquí podés optar (entre otras) por:

  • Guardar los logs en un archivo compartido entre los servidores (por ejemplo por NFS o similar)… poco recomendable (mala performance, mala seguridad, etc…)
  • Guardar los logs en una base de datos compartida
  • Enviar los errores directamente por email

Y aquí es donde te conviene empezar a pensar en usar alguna librería que maneje todo esto… como por ejemplo Monolog.

Monolog es precisamente eso: una librería hecha especialmente para manejar procesos de logging complejos. Permite entre otras cosas diferenciar almacenamiento de logs en función de la gravedad de los sucesos (que vos también podés definir).

Como para empezar a probarla podés instalarla usando composer:

composer require monolog/monolog

Y luego, la podés empezar a usar en tu aplicación con algo como:

<?php

require_once 'vendor/autoload.php';

use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('mi-canal');
$log->pushHandler(new StreamHandler(__DIR__.'/mi-app.log', Level::Warning));

$log->warning('Este es un warning');
$log->error('Este es un error');

Después de ejecutar este código, abrí el archivo mi-app.log y te encontrarás con algo como:

[2025-01-08T08:44:02.872376+00:00] mi-canal.WARNING: Este es un warning [] []
[2025-01-08T08:44:02.873235+00:00] mi-canal.ERROR: Este es un error [] []

Una característica interesante de este tipo de logs es que son fácilmente filtrables usando una herramienta como grep. Por ejemplo, para buscar sólo los errores podés usar un comando como cat mi-app.log | grep ERROR para obtener:

[2025-01-08T08:44:02.873235+00:00] mi-canal.ERROR: Este es un error [] []

Así que dale, instalá monolog, configuralo y empezá a generar logs poderosos en tus aplicaciones.

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a afinar sus habilidades técnicas y avanzar en sus carreras