En esta nueva entrega de la publicación Trazabilidad y control de errores vamos a centrarnos en el que es quizá el más interesante aspecto de la trazabilidad. Structured Logging es la técnica que nos permitirá realizar análisis automatizados de nuestra trazabilidad, mediante software de detección de eventos.
Definimos los atributos, correspondientes a las informaciones que queremos guardar. recuerden recurrir a la documentación de NLog para verificar todas las opciones posibles, que son muchas. En nuestro caso en nuestro fichero JSON reflejaremos el tipo de excepción y el mensaje, y un valor interesante, la propiedad Data.
En la primera parte de la publicación incorporamos a nuestra plataforma de test Open Source la librería NLog, y configuramos la generación de dos ficheros de texto plano para trazas, uno para dejar la información de los posibles errores no controlados, y otro para los avisos, o warnings. Además asociamos la consola para crear trazas de información para la depuración.
Hoy vamos a configurar la creación de un tercer fichero, que almacenará igualmente información de los errores, pero en este caso guardará la información no en texto plano, sino estructurada, con notación JSON que después podría ser procesada.
Para este fin NLOG nos proporciona el JSON Layout. Vamos a ponernos manos a la obra. Lo primero que haremos será ir al web.config, donde encontramos nuestra configuración para NLOG, y ahí crearemos un nuevo target:
<target name="jsonlogfileerror" xsi:type="File" fileName="logs/jsonerror_${shortdate}.txt"> <layout type='JsonLayout'> <attribute name='type' layout='${exception:format=Type}' /> <attribute name='message' layout='${exception:format=Message}'/> <attribute name='data' layout='${exception:Data}'/> </layout> </target> </targets>
Data es una propiedad de las excepciones que ofrece gran versatilidad. Se trata de un diccionario cuyos valores pueden ser informados por el programador en el momento en que se genera la excepción, y podemos usarla, entre otras cosas, para guardar el contexto del error.
Vamos a seguir con el ejemplo del Test1: multithreading vs singlethreading que ya usamos en la primera entrega de este post. Aquí tenemos el testcase MultithreadingCaseWithErrors donde estamos generando un par de errores no controlados durante la ejecución del proceso. Vamos a ver cómo en el control de errores informamos la propiedad Data de la excepción:
private static void CalcFiboWithErrors(int index) { try { _logger.Info("Inicia cálculo serie Fibo - Index " + index.ToString()); if (index == 1) { //error 1: object o2 = null; int i2 = (int)o2; } else if (index == 2) { //error 2: int a = 0; int b = 1 / a; } fibo_functions.CalcFibo(200); _lst_process_control[index].Estado = objects.process_control.enumEstadoProceso.Finalizado; _logger.Info("Finaliza cálculo serie Fibo - Index " + index.ToString()); } catch (Exception ex) { ex.Data.Add("test", "test1_multithreading_vs_singlethreading"); ex.Data.Add("case", "CalcFiboWithErrors"); ex.Data.Add("index", index.ToString()); _logger.Error(ex, " CalcFiboWithErrors - Index " + index.ToString()); _lst_process_control[index].Estado = objects.process_control.enumEstadoProceso.Erroneo; } }
Tan solo configurando un target para el JSON Layout en el web.config, sin tocar nada más, obtenemos un segundo fichero de errores cuyo contenido paso a mostrarles:
Como podrán Uds. deducir, la ventaja de este fichero respecto del anterior en formato de texto plano es la estructura, que nos facilitará el tratamiento automatizado de las excepciones. Para ello disponemos de muy distintas opciones. Una es usar el Database Target, y directamente guardar las trazas en una base de datos dedicada sobre la que poder implementar sus propias consultas.
NLOG también admite protocolos de red, por lo que puede Ud. personalizar su propio servidor HTTP por ejemplo, para implementar un tratamiento personalizado.
Por otro lado buscando en la web también encontrará multitud de herramientas ya desarrolladas, de mayor o menos complejidad.
A modo de ejemplo les presento la solución Seq, de instalación y uso muy agradable. Pasos a seguir:
1. Instalar MSI aquí.
2. Instalar Nuget:
Install-Package NLog.Targets.Seq
3. Configurar en web.config:
<!--NLOG Configuration--> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true"> <extensions> <add assembly="NLog.Targets.Seq"/> </extensions> <variable name="ExceptionLayout" value="${machinename} | ${longdate} | ${level:upperCase=true} | ${message} | ${exception:format=ToString,Properties,Data} " /> <targets async="true"> <default-target-parameters xsi:type="File" keepFileOpen="false"/> <target name="logconsole" xsi:type="Console" /> <target name="logfilewarning" xsi:type="File" fileName="logs/warning_${shortdate}.txt" /> <target name="logfileerror" xsi:type="File" fileName="logs/error_${shortdate}.txt" layout="${ExceptionLayout}" /> <target name="jsonlogfileerror" xsi:type="File" fileName="logs/jsonerror_${shortdate}.txt"> <layout type='JsonLayout'> <attribute name='type' layout='${exception:format=Type}' /> <attribute name='message' layout='${exception:format=Message}'/> <attribute name='data' layout='${exception:Data}'/> </layout> </target> <target name="seq" xsi:type="Seq" serverUrl="http://localhost:5341" apiKey=""> <property name="type" value="${exception:format=Type}" /> <property name="message" value="${exception:format=Message}" /> </target> </targets> <rules> <logger name="*" minlevel="Debug" maxlevel="Warn" writeTo="logconsole" /> <logger name="*" minlevel="Warn" maxlevel="Warn" writeTo="logfilewarning" /> <logger name="*" minlevel="Error" writeTo="logfileerror" /> <logger name="*" minlevel="Error" writeTo="jsonlogfileerror" /> <logger name="*" minlevel="Error" writeTo="seq" /> </rules> </nlog>
4. Navegar a http://localhost:5341/ para obtener este resultado:
Bonito ¿verdad?
Llegados a este punto amigos, me pregunto si no sería ésta la ocasión perfecta para montar con C# un servidor UDP, o una WebApi... y construir nuestro servicio personalizado de captación de excepciones.
Déjenme saber si desean una tercera entrega sobre esta fascinante disciplina de la trazabilidad. De pronto en próximas publicaciones les presentaré un nuevo proyecto Open Source ya disponible en HitGub. Se trata de una interpretación personal del patrón Command and Query Responsibility Segregation (o CQRS), útil cuando topamos con sistemas de alta exigencia de lecturas y de escrituras. Les aseguro que es un proyecto apasionante en el que pondremos al límite los recursos del sistema.
Comentarios
Publicar un comentario