Este sitio utiliza cookies de Google para prestar sus servicios y analizar su tráfico. Tu dirección IP y user-agent se comparten con Google, junto con las métricas de rendimiento y de seguridad, para garantizar la calidad del servicio, generar estadísticas de uso y detectar y solucionar abusos.Más información

View site in english Ir a la página de inicio Contacta conmigo
viernes, 14 de julio de 2017

La importancia de tener un buen log

Muchas veces descuidamos, por falta de tiempo, inexperiencia o por simple pereza, el dotar a nuestros desarrollos de unos buenos mecanismos de seguimiento de la actividad, lo que tiene como consecuencia un aumento sustancial de la dificultad y el tiempo necesario para determinar las causas de ciertos errores que se detectan bastante tiempo después de haberse producido, cuando el estado del sistema puede haber cambiado sustancialmente.

El tiempo que dediques a esta parte de la aplicación nunca es tiempo perdido, sino todo lo contrario. Es posible que en desarrollos simples muchas veces sea innecesario complicarse la existencia con desarrollos adicionales que no nos van a aportar ningún valor añadido, pero la cosa cambia sustancialmente cuando el sistema en el que estamos trabajando comprende varios procesos simultáneos y una o más bases de datos. Aquí, localizar la causa de un error que puede haber pasado desapercibido durante varias horas o días, o un cuello de botella en la maraña de procedimientos puede ser un quebradero de cabeza que nos lleve días o incluso semanas, a veces hasta meses o años.

El log no es solamente un archivo en el que se van registrando los errores. En el log se debe registrar toda la información que pueda ser relevante para estudiar la historia de la evolución del sistema. Un sistema distribuido puede tener un buen número de archivos de log diferentes, además de información de seguimiento registrada en las bases de datos. Si todo ello va acompañado de la fecha y la hora en la que se han producido los eventos, resulta trivial reconstruir lo que ha sucedido en el sistema en un momento determinado, al menos en comparación con los quebraderos de cabeza resultantes de intentar averiguarlo sin este preciado recurso.

Podéis pensar que esto puede repercutir de manera negativa en el rendimiento del sistema, pero esto no es así necesariamente. No se tarda demasiado en escribir una línea en un fichero de texto, y se puede realizar de forma asíncrona, ya que no resulta relevante para el funcionamiento normal del sistema. Tampoco cuesta nada registrar de manera sistemática la fecha de creación de un registro de la base de datos, se trata de añadir un simple campo de tipo DateTime. Si esto está incluido en el diseño desde un principio, la carga de trabajo añadida es mínima con respecto al ahorro posterior en tiempo de monitorización y depuración.

A continuación, voy a comentar algunos de los pasos que sigo yo para hacer que la vida sea más fácil una vez que los sistemas pasan a producción, os aseguro que funciona de maravilla y nunca agradeceréis lo suficiente haber seguido mis consejos. Si ya lo hacéis, seguro que sabéis de qué estoy hablando.

Seguimiento de actividad en la base de datos

Es posible que os hayáis tenido que enfrentar en algún momento con una base de datos en la que continuamente se están creando multitud de registros, muchos de ellos generados por procesos que insertan o actualizan datos en multitud de tablas diferentes. Si algo falla, o existen problemas de rendimiento, resulta un infierno descubrir cuándo y en qué lugar se están produciendo dichos problemas.

La solución es fácil. Aunque no es necesario hacerlo en todas las tablas, no hay que ser nunca cicatero con los campos de tipo fecha. Añadid siempre un campo con la fecha de creación del registro, y quizás otro con la de la última modificación (aunque esto resulta bastante menos útil) y, por supuesto, todas las fechas necesarias para indicar los diferentes cambios de estado del registro (fecha de cierre, fecha de verificación, etc.). Esto sirve para construir consultas SQL con la unión de todos los registros que queramos analizar ordenadas por la fecha de interés.

De esta manera, resulta sencillo detectar, por ejemplo, el punto exacto donde se produce un problema de rendimiento en un proceso consistente en integrar un gran número de registros en varias tablas, simplemente observando el tiempo que pasa entre la creación de un registro y el siguiente. El punto donde detectemos un salto sospechoso servirá de pista para localizar el punto del código donde se está creando dicho registro, y allí estará el origen del problema.

También resulta de gran ayuda para determinar el orden en que se han producido determinados eventos y localizar problemas de sincronización y cosas por el estilo.

Algo que ya no resulta tan sencillo de hacer, y además puede originar problemas de rendimiento o almacenamiento, consiste en guardar, para cierta información sensible, un histórico de cambios de los registros, incluyendo los registros eliminados, también con su fecha correspondiente. En cualquier caso, no resulta conveniente que estos datos se almacenen junto con los datos de producción, siempre es mejor hacerlo en bases de datos diferentes o en esquemas que utilicen ficheros de datos diferentes.

Log de actividad de las aplicaciones

Aunque es posible que el sistema operativo proporcione servicios de registro de eventos, como pasa por ejemplo en Windows, yo siempre prefiero desarrollar mis propios mecanismos de registro, pues me permite un control total del sistema de log.

Lo más sencillo es recurrir a la inyección de dependencias para poder crear varios componentes que implementen diferentes mecanismos de registro, que incluso pueden encadenarse para registrar los datos en diferentes medios, como puede ser el registro del sistema, una base de datos, ficheros de texto con diferentes formatos o incluso una clase que no haga nada y pueda servir para desactivar el registro sin tener que andar comprobando en todas partes si está o no activo.

Para ello, basta con definir en primer lugar un interfaz que será común a todas las clases que implementen la tarea de registro, puede bastar con un simple método al que se le pase un mensaje y un grado de severidad, que se puede utilizar también para decidir que eventos se registran y cuáles no.

Es importante que el log esté centralizado y sea único para evitar que se produzcan errores derivados de accesos simultáneos al mismo fichero y cosas por el estilo. En una aplicación MVC, por ejemplo, resulta sencillo crear una clase derivada de ActionFilterAttribute y añadirla al conjunto de filtros en el método RegisterGlobalFilters de la clase FilterConfig. El método OnActionExecuted, por ejemplo, será llamado cada vez que se ejecute una acción de uno cualquiera de los controladores.

En una aplicación de escritorio, se puede utilizar, por ejemplo, un método static de una de las clases que estén accesibles en todo el ámbito de la aplicación. Este método debería tener acceso a algún tipo de mecanismo de configuración que permita determinar la clase que se va a utilizar para realizar el registro, de manera que la podamos cambiar sin necesidad de parar y reiniciar la aplicación. En entornos multitarea también será normalmente necesario implementar mecanismos apropiados para que solamente acceda al registro un solo proceso cada vez.

Como veis, resulta muy sencillo implementar mecanismos de registro. Os aseguro que merece la pena y os lo recomiendo encarecidamente.

Comparte este artículo: Compartir en Twitter Compártelo en Facebook Compartir en Google Plus Compartir en LinkedIn
Comentarios (0):
* (Su comentario será publicado después de la revisión)

E-Mail


Nombre


Web


Mensaje


CAPTCHA
Change the CAPTCHA codeSpeak the CAPTCHA code