Mostrando entradas con la etiqueta Logging. Mostrar todas las entradas
Mostrando entradas con la etiqueta Logging. Mostrar todas las entradas

sábado, 9 de enero de 2016

Utilizando NLog con MonoDevelop en .NET

Para cualquier aplicación de software a nivel producción es indispensable tener un componente que escriba los eventos más significativos en una bitácora. Esta acción que se conoce como logging (escribir en la bitácora) se define técnicamente como:

“Una forma sistemática y controlada para obtener el estado de una aplicación en tiempo de ejecución.”

Pensando en esto, los diseñadores de .NET incorporaron un mecanismo de logging de forma predeterminada dentro del ensamblado System.Diagnostics, en clases como Trace, TraceListener, Swicth y todas sus clases derivadas. Aunque el empleo de estas clases es efectivo, no deja de ser rudimentario y carecer de muchas funcionalidades que terminan siendo un límite.

Teniendo en cuenta esto, en el ecosistema .NET han surgido a lo largo de los años una cantidad de componentes propietarios y opensource para el logging de aplicaciones. Dentro de ese conjunto hay un componente que se destacado y es del que trataré de resumir en este tutorial: Nlog.

¿Qué es NLog?

Nlog (http://nlog-project.org/) es un componente open source de logging para .NET, que entre sus características se encuentran:

  • Muy fácil de configurar.
  • Extremadamente personalizable con plantilla (layouts)
  • Altamente extensible

Hay tres características que se deben conocer antes de empezar su utilización:

  1. Targets: Se utilizan para enviar los mensajes hacia otro destino, entiéndase aquí un archivo, una base de datos, un email, la consola, un webservice, etc.
  2. Layouts: Con los comandos de layout podemos definir la estructura o el molde de como acomodar la información escrita en un determinado target.
  3. Levels: Es una forma de asignar una prioridad al mensaje, los niveles permitidos son los siguientes:
    1. Fatal: Sucedió algo que causo que el todo el sistema entero falle, se debe detener la ejecución.
    2. Error: Un problema ha ocurrido pero no es fatal, el sistema puede seguir funcionando.
    3. Warn: Un problema ha ocurrido, pero puede ser recuperable.
    4. Info: Mensajes de información muy útiles como cambios de estado, login/logout, etc.
    5. Debug: Se utiliza durante el desarrollo del sistema.
    6. Trace: Para indicar el inicio y final de una rutina.

Como un primer acercamiento a su utilización, escribí una aplicación de consola en C# que solicita una cadena de conexión, con esta cadena trata de conectase a una base de datos PostgreSQL, si la cadena de conexión no es correcta se utiliza Nlog para enviar la excepción a consola, si logra conectarse solicita una consulta SELECT para ejecutar y mostrar los resultados en la consola. Aquí de nuevo si ocurre una excepción utiliza Nlog para notificarla.

1-. Ejecutar Monodevelop y seleccionar un proyecto de consola y nombrarlo como HelloNlog

Fig. 1 crear un proyecto llamado HelloNlog

2-. Dentro del Solution Explorer has click con el botón derecho y has click en Add Packages , entonces aparecerá la pantalla Add Packages, ya en esa pantalla usa el buscador para encontrar el paquete Nlog, y seleccionar los paquetes: Nlog, Nlog Configuration y Npgsql respectivamente, presionar el botón Add Packages para agregar los ensamblados al proyecto.

Fig. 2 seleccionar los paquetes Nlog y Nlog Configuration

3-. Ahora que ya se tiene una estructura en la solución como se muestra en la siguiente imagen:
Fig. 3 la estructura de la solución con los ensamblados.

4-. Agregar al proyecto una clase llamada NloggerWrapper
5-. Bien ahora hay que completar el código de la clase Program.
6-. Antes de ejecutar la solución es muy importante editar el archivo Nlog.conf para agregar targets (objetivos), layouts (disposición) y rules (reglas). Aquí el código del archivo Nlog.conf del proyecto.

Targets

En este archivo de configuración defino tres targets, el primero hacia un archivo, el segundo hacia una consola con salida de color y el último hacia una consola de salida normal.

Para ver completa la lista de targets consultar el enlace: https://github.com/NLog/NLog/wiki/Targets

Layouts

Por cierta comodidad y porque así es la manera predeterminada de ver la información, puse los layouts de la siguiente manera:

Se especifica un layout por cada uno de los targets Para más información de los layouts ver el siguiente enlace: https://github.com/NLog/NLog/wiki/Layout-Renderers

Rules

Ahora la configuración para las rules, aquí con el '*' le indico que ese nivel se use para todos los logs, únicamente en los niveles Error y Fatal escriban hacia el target llamado fileLog que es el target que escribe hacia un archivo de texto, en la segunda regla indico igual que para todos logs, los niveles Trace se escriban hacia el log llamado consoleLog que tiene la salida normal de consola y por último le indico que para los niveles Warn y Info escriban hacia el log de la consola con colores.

Para más información de las reglas ver el siguiente enlace: https://github.com/nlog/NLog/wiki/Configuration-file#rules

8-. Antes de ejecutar el programa, en el Solution Explorer haz click derecho sobre la solución después haz click en options, aparecerá la ventana Project Options ahí seleccionar las opciones run on external console y pause console output.
Fig. 4 opciones para ejecutar el proyecto.

Bien al ejecutar el programa este solicita una cadena de conexión desde el inicio:
Fig. 5 el programa solicita una cadena de conexión.

Errores como si la cadena de conexión no tiene un formato correcto, el servidor Postgresql esta abajo o no existe la base de datos, etc. Son encerrados dentro por un bloque try/catch y enviados al método LogException para que Nlog utilice el level correspondiente y lo mande hacia el target. Aquí el código del método LogException dentro de la clase NLoggerWrapper

    public static void LogException(Exception ex)
  {
   if (ex is ArgumentException)
    logger.Warn (ex.Message);
   else
   if (ex is NpgsqlException)
    logger.Error (ex.Message);
   else
    logger.Fatal (ex.Message);
  }
En este código dependiendo del tipo de excepción utiliza un nivel (level) de Nlog para escribir.
Fig. 6 el programa con Nlog muestra las excepciones en la consola con color..

Fig. 7 excepción atrapada por Nlog que se muestra en color.

Cuando uno de los target como en este ejemplo esta dirigido a escribir en archivo se puede revisar la creación del archivo y posteriormente su contenido.

Fig. 8 la creación de los archivos log con el target File.

Fig. 9 el formato de los archivos log.

Fig. 10 la ejecucción del programa sin errores

sábado, 30 de julio de 2011

Entendiendo Logging en Aplicaciones .NET con Log4net

Esta entrada se relaciona con esta entrada anterior, que trata también sobre el tema de Logging.
Log4net es opción altamente recomendable para la implementación del logging en las aplicaciones desarrolladas para .NET. Sobre todo cuando se necesita una solución más configurable y robusta que la proporcionada por las clases del ensamblado System.Diagnostics, que en comparación con log4net están en un nivel elemental, si necesitamos una herramienta que soporte diferentes fuentes de persistencia, que no afecte el desempeño de las aplicaciones y que sea transportable entre la implementación .NET de Microsoft y la del proyecto Mono.

Log4net es un Framework open source creado por la fundación Apache basado en la implementación de los servicios de logging existentes en log4j, un componente de logging usado durante años en los ecosistemas Java.
La arquitectura de Log4net puede resumirse en tres clases principales cada una encargada de una responsabilidad dentro del Framework y que se detalla a continuación:

  • Logger Captura la información para la bitácora.
  • Appender Publica la información hacia diversas fuentes de logging configuradas en la aplicación. Al menos debe definirse un Appender, el Appender predeterminado es el ConsoleAppender cual dirige su salida hacia una terminal de Consola.
  • Layout Se utiliza para darle formato haciendo legible cada salida de los distintos Appenders.

Para más información consultar http://logging.apache.org/log4j/1.2/manual.html aunque es para log4j la arquitectura es idéntica a log4net.

Como ejemplo del uso de log4net vamos a crear dos programas un cliente y un servidor los cuales se comunicarán entre sí, la clase ServerProgram es un servidor TCP que escucha en el puerto 6060 y la clase Program que es el cliente que al conectarse con el servidor, le solicita al usuario el nombre de un archivo de texto el cuál sera leído y cada línea de texto será enviada hacia el servidor. El programa cliente implementa todo el código básico para el manejo del logging con log4net.


Código de la clase ServerProgram
Código de la clase Program (cliente)

El archivo de configuración App.config en donde van las opciones de configuración de Log4net

En el archivo de configuración utilizamos el declarado en la siguiente sección
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt"/>
<appendToFile value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%date{dd-MM-yyyy HH:mm:ss}] [%level] %message %newline"/>
</layout>
</appender>
Declaración del componente principal para implementar los métodos del Logger.
static readonly log4net.ILog log = log4net.LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
carga la configuración del archivo de configuración para Log4net.
XmlConfigurator.Configure();
Escribir una excepción al log.
log.Error(ex.Message, ex);
Escribir información al log
log.Info("Ejecutando la aplicación en " + DateTime.Now.ToLongTimeString());
Compilando los programas:

Ejecutando el servidor

Ejecutando el cliente

Generando excepción de formato

Generando excepción de comunicación

Revisando el archivo de log, creado por log4net

martes, 31 de mayo de 2011

Entendiendo Logging en Aplicaciones para .NET Framework

El logging es un proceso recomendado durante la etapa de pruebas e indispensable durante la etapa de liberación o puesta en producción de aplicaciones de software, logging se refiere a la utilización de una bitácora, registro o log, donde guardemos la información de los diferentes eventos que genero la aplicación entre el tiempo de arranque y durante el tiempo de ejecución.
El registro o log debe proporcionarnos toda información necesaria para realizar con la aplicación las siguientes actividades:

  1. Mantener el rastro de todos sus estados (recording)
  2. Depurar (debugging)
  3. Auditar (audit)
  4. Diagnosticar su estado actual (tracing)

Un factor importante a considerar durante el logging es el performance de la aplicación ya que es un hecho que se incrementará el tiempo de las operaciones de escritura, sobre todo si el logging es requerido para una auditoría, este incremento en el performance se explica de la siguiente manera:

Si una operación del proceso de negocio emplea 5 segundos para ejecutarse y producir un resultado, con el logging necesitará 2 o 3 segundos adicionales para registrarse en el log, por lo que ahora el tiempo es de 7 u 8 segundos para el total de la operación.


El siguiente fragmento de código ilustra este factor:

try
{
//operación de negocio 5 segs.
var output = BussinessObject.ExecuteOperation();
//registro en el log 3 segs.
Logger.WriteLine(output);
//El tiempo total de la transacción es de 8 segs.

}catch(Exception e){

//No está incluído dentro de la transacción.
Logger.WriteLine(e.Message);

}

Hay muchas formas de implementar logging en las aplicaciones, esto varía dependiendo del tipo de aplicación y del requerimiento a satisfacer la forma más sencilla es mediante el uso de las clases contenidas en el ensamblado System.Diagnostics. específicamente con las implementaciones derivadas de la clase TraceListener las cuales son responsables de desplegar o de guardar los mensajes generados por las clases Trace y Debug, hay tres implementaciones de esta clase:

  1. TextWriterTraceListener escribe mensajes a cualquier clase que se derive de Stream
  2. EventLogTraceListener escribe los mensajes a el Event Viewer de Windows.
  3. DefaultTraceListener escribe los mensajes a la ventana de salida (Output window).

El siguiente listado muestra el uso de TextWriterTraceListener y EventLogTraceListener, la lógica del programa es simple, si el programa tiene permisos administrativos usará el event viewer como log, de lo contrario usará un archivo de texto, realizando un intercambio entre los Tracelisteners: EventLogTraceListener y TextWriterTraceListener respectivamente.

Al compilar el listado se debe de incluir la opción /d:TRACE como se muestra en la siguiente imagen:

Al ejecutar el programa mostrará un resultado como en la siguiente imagen:

Con el siguiente código el programa intercambia entre Listeners dependiendo si pertenece al grupo con permisos de administración o no.

Si no pertenece al grupo de administradores utiliza como log un archivo de texto log.txt caso contrario utiliza el Event Viewer (visor de eventos de Windows) como se muestra en la siguiente imagen:


Lo más recomendable para el logging es la utilización de componentes como el Logging Application Block de Microsoft o el Log4net de la fundación Apache.