No subestimes el poder de un log

Desarrollar software sería mucho más fácil (aunque tal vez menos divertido) si todo funcionase siempre. La realidad es que, por muchos tests automátizados que escribas y muchos motivos que tengas para cuidar la calidad del software, antes o después, te encontrarás con problemas de lo más exótico que jamás hubieses pensado que podrían llegar a producirse.

Si tienes suerte, darás con un usuario muy colaborador que te proporcionará una lista exacta de los pasos necesarios para reproducir el problema, podrás reproducirlo en un entorno de desarrollo y, usando toda tu artillería pesada de depuradores, monitores, sniffers y demás, conseguirás solucionarlo.

Si vives en el mundo real, es probable que muchos de esos problemas se produzcan en condiciones extrañas, con usuarios que “no saben que han hecho, pero la aplicación falla”, y sean muy difíciles de diagnosticar (no digamos ya de reproducir en un entorno de desarrollo).

Para estos casos, hay una herramienta que, por su simplicidad, resulta muy útil: un buen log.

Existen muchas formas de obtener información sobre el comportamiento de una aplicación una vez que llega a producción. Por ejemplo, puedes conseguir estadísticas de uso, puedes guardar información de errores o puedes mantener un histórico con las acciones realizadas por los usuarios con fines de auditoría. Todo esto lo puedes hacer de forma “artesanal” o integrándolo con sistemas más potentes y estandarizados como contadores de rendimiento, eventos de windows, syslogs, etc.

Teniendo en cuenta que existen todos estos sistemas que permiten mantener enormes históricos y realizar complejas consultas y análisis, ¿tiene sentido escribir un triste log en un fichero de texto?

El poder de la simplicidad

La ventaja fundamental de un fichero de log frente a sistemas más potentes es su simplicidad.

Generar un fichero de texto plano es fácil desde cualquier lenguaje de programación, no requiere desplegar servicios externos (o usar servicios de terceros) para almacenar la información, se puede consultar con cualquier editor de texto en cualquier dispositivo y se puede compartir de mil formas diferentes, desde un email hasta una memoria USB.

Esto permite que generar un log suponga una inversión inicial muy baja y no tengamos que dedicar mucho esfuerzo a montar una infraestructura más potente hasta que no sea necesaria (vamos, YAGNI y todas esas siglas que molan tanto).

No obstante, con el paso del tiempo, es posible que merezca la pena automatizar ciertos procesos relativos a la obtención de los logs. Por ejemplo, puede ser interesante poder realizar un envío automático de logs desde la aplicación (o con una herramienta externa, por si la aplicación ni siquiere arranca), solicitar remotamente el envío de esos logs para equipos que no están siempre conectados, o al menos ayudar al usuario a preparar un zip con los logs que luego pueda copiar a una memoria USB.

Aprovechar esta simplicidad no quiere decir que dejemos de lado otros mecanismos más potentes. Por suerte, la mayoría de librerías de logging disponibles permiten enviar información a distintos almacenes, y por el mismo precio que generamos nuestro humilde fichero de log podemos ir alimentando una base de datos, el visor de sucesos de windows o un syslog.

Qué información debe contener un buen log

La utilidad de un log va a depender directamente de la calidad de la información que contenga. Si partimos de la base de que nuestro objetivo fundamental con el log es resolver problemas, parece claro que la información que debemos incluir en el log es aquella información que nos gustaría tener cuando ocurra un problema.

El log debe contener información relevante para la aplicación, que nos permita saber qué está ocurriendo en todo momento en la aplicación, por ejemplo, cuando si estuviésemos hablando de un cliente de twitter, un log debería poder mostrar los intentos de enviar un tweet que hace el usuario o el número de tweets descargados cada vez que se conecta al servidor.

Junto a este tipo de información, también puede resultar útil almacenar información del entorno de ejecución: versiones de aplicación, sistema operativo y plataforma (CLR, JRE, etc.), usuario de sistema que ejecuta la aplicación, ruta de ejecución, etc. Además, podemos incluir una monitorización cada cierto tiempo para controlar aspectos como la cantidad de memoria disponible, el nivel de batería (si procede), si hay conexión disponible o no…

Todo esto depende mucho del tipo de aplicación, pero a veces es necesario contar con esta información para tener un cierto contexto que nos ayude a comprender por qué se produjo ese OutOfMemoryException o por qué dejó de responder la resolución DNS.

A la hora de presentar esta información en el log debemos tener en cuenta que debe ser fácilmente legible para un humano (probablemente nosotros) y sería de agradecer que fuese más o menos sencillo buscar cosas en él desde un editor de texto normal, ya sea con subcadenas o con expresiones regulares.

Merece la pena dedicar un poco de tiempo a formatear correctamente los mensajes en el log para que sean homogéneos y realmente nos ayuden a seguir lo que está pasando en la aplicación.

Es especialmente importante registrar en el log la forma en que se desarrollan procesos desatendidos. Volviendo al cliente de twitter, si va a estar actualizando datos en background, es importante registrar esos intentos de actualización para poder diagnosticar problemas cuando el usuario nos diga “no recibo nuevos tweets” y tengamos que decidir si es que se ha colgado la hebra que los actualiza, hemos dejado de recibir notificaciones push, no hay cobertura, el servidor está caído, o realmente no hay ningún tweet que recibir.

Otro punto en el que un buen log puede salvarnos muchas horas de depuración es en la integración con sistemas externos. Tener información del tiempo que tardan en respondernos o la información que se intercambia con ellos (en la medida de lo posible) puede ser vital a la hora de decidir si el problema está en el sistema externo o en nuestra aplicación (sí, nuestras aplicaciones también puedes tener problemas).

Qué información NO pertenece a un log

Hay información que no pertenece a un fichero de log (aunque podamos incluirla en él), sino que forma parte de los requisitos propios de la aplicación. Por ejemplo, si nuestra aplicación debe mantener un histórico de qué usuario modifica qué productos, eso deberá tratarse de forma adecuada en la aplicación y no sólo como entradas en el log.

Podemos tener casos en que necesitamos tener información para realizar una monitorización proactiva del sistema (memoria en uso, peticiones por segundo, etc.). En ese caso esta información deberá estar disponible por otros medios más adecuados que un log, que no deja de ser una herramienta reactiva, es decir, para cuando ya ha ocurrido el problema.

Por último, tampoco debemos incluir en el log toda la información de llamadas a métodos que se realizan en la aplicación. Esto, que es muy tentador cuando uno empieza a jugar con AOP y cosas como PostSharp, en realidad forma parte de una traza, no de un log, y en el log lo más que puede hacer es generar ruido y dificultarnos encontrar la información relevante para el problema que necesitamos resolver.

Conclusiones

Cuando no tenemos la opción de engancharnos a un depurador para ver qué está pasando con una aplicación que da problemas, utilizar un simple fichero de log puede ser extremadamente útil para resolver el problema.

A la hora de generar el log debemos definir claramente qué tipo de información necesitamos guardar en él y hacerlo de forma ordenada para que, cuando sea necesario revisarlo, realmente resulte útil y no sea una amalgama sin sentido llena de ruido e información redundante.

Al final, la última línea de soporte somos nosotros, y cuando llega el momento de solucionar un problema, contar con las herramientas adecuadas puede ser la diferencia entre resolver un problema en un rato o sufrirlo durante días.


Un comentario en “No subestimes el poder de un log

  1. Muy interesante Juanma, sobre todo el apunte de crear el log pensando en que después se buscará en él y ahí subcadenas o expresiones regulares serán de gran ayuda!
    Un saludo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>