Comenzamos con el primer post de DunkedNetNuke hablando de una de las funcionalidades agregadas a partir de la versión 6 de DNN, log4net. Esta herramienta os sonará por ser un port de la excelente herramienta Apache log4j™ framework al entorno Microsoft aprovechando todas las nuevas características que aporta .NET, para ofrecernos un sólido sistema de generado y envío de logs a múltiples destinos.
Para configurar esta funcionalidad solo tenemos que acceder al archivo DotNetNuke.log4net.config en el que podremos ver la salida de todos los logs que deseemos crear. Por defecto se incluye la generación de logs de todos los registros de errores en la aplicación web dirigidos a Portals/_default/Logs. Por esto si nuestro sistema de logging va a ser otro sería interesante no almacenar estos registros desactivando este appender por defecto cambiando los level value a "OFF".
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="Portals/_default/Logs/" />
<datePattern value="yyyy.MM.dd'.log.resources'" />
<rollingStyle value="Date" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="5" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline" />
<locationInfo value="true" />
</layout>
</appender>
<root>
<level value="Info" />
<appender-ref ref="RollingFile" />
</root>
<logger name="DotNetNuke.Services.Localization.LocalizationProvider">
<level value="ERROR" />
</logger>
</log4net>
Podemos ver como cada salida de los logs se genera mediante un appender, en el que se definen la configuraciones de la misma para finalmente usarlo en un logger. Se pueden crear tantos appender y loggers como salidas distintas queramos generar.
Ahora vamos a añadir un nuevo appender a nuestro logger para fijar como salida un broadcast udp constante que muestre únicamente los errores del aplicativo:
Creamos el nuevo appender
<appender name="UDPBroadcast" type="log4net.Appender.UdpAppender">
<param name="RemoteAddress" value="127.0.0.2" />
<param name="RemotePort" value="877" />
<param name="Threshold" value="ALL" />
<layout type="log4net.Layout.XmlLayout">
<locationInfo value="true" />
</layout>
</appender>
Lo asignamos dentro de la etiqueta root o creamos un logger para el.
<level value="info" />
<appender-ref ref="RollingFile" />
<level value="ERROR" />
<appender-ref ref="UDPBroadcast" />
Como podréis observar hemos definido un nivel diferente de generación de logs "ERROR" ya que solo nos interesa obtener los errores y no toda la información que genera nuestra instancia de DNN, no olvidemos que lo vamos a enviar en un flujo de datos constante por la red. Esta práctica nos puede venir muy bien para las fases de desarrollo ya que nos permite ver de forma constante todos registros de la aplicación que nos interesen.
Para recibir el flujo y visionarlo podremos usar cualquier aplicación de consumo de broadcast, en este caso usaremos log4view con la siguiente configuración:
Si usáis Windows 7 o posteriores y hacéis pruebas en local usad la ip de loopback terminada en 2, cosas que tiene IPv6
Con esto ya tendremos nuestro receiver configurado por lo que comenzaremos a captar los errores enviados mediante el broadcast UDP generado por log4net.
Ahora procederemos a crear el envío de errores críticos vía email para lo que agregaremos otro appender:
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="correo@destino.com" />
<from value="correo@envío.com" />
<subject type="log4net.Util.PatternString" value="Fatal Error Host: %property{log4net:HostName} Error: %appdomain" />
<smtpHost value="smtp.tuservidorsmtp.com" />
<authentication value="Basic" />
<port value="587" />
<username value="Usuario" />
<password value="Contraseña" />
<bufferSize value="1" />
<EnableSsl value="false"/>
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ALL"/>
</evaluator>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFile" />
<level value="ERROR" />
<appender-ref ref="UDPBroadcast" />
<level value="FATAL" />
<appender-ref ref="SmtpAppender" />
</root>
De esta forma conseguiremos que en caso de que un error crítico suceda, en pocos momentos tengamos una alerta con información importante para su rápida resolución:
El ejemplo anterior ha sido realizado para una conexión con un servidor SMTP con autenticación básica mediante el protocolo TLS pero si quisiéramos enviar nuestro correo por ejemplo desde una cuenta personal desde gmail tendríamos que usar la siguiente configuración para habilitar SSL y permitir a gmail usar fuentes no seguras para el envío de correos.
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="receptor@intelequia.com" />
<from value="usuario@gmail.com" />
<subject type="log4net.Util.PatternString" value="Fatal Error Host: %property{log4net:HostName} Error: %appdomain" />
<smtpHost value="smtp.gmail.com" />
<authentication value="Basic" />
<port value="587" />
<username value="usuario@gmail.com" />
<password value="contraseña" />
<bufferSize value="1" />
<EnableSsl value="true"/>
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ALL"/>
</evaluator>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline" />
</layout>
</appender>
Y habilitamos el uso de fuentes no confiables o nuestros correos no llegarán al servidor smtp de gmail
Por último en muchas ocasiones tendremos que depurar el funcionamiento del propio log4net, para ello podemos generar a su vez un log del funcionamiento de este agregando estas líneas al fichero web.config de nuestra aplicación dentro de <configuration></configuration>:
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\websites\miweb.dnndev.me\log4net.txt" />
</listeners>
</trace>
</system.diagnostics>
De esta forma tendrás un nuevo log en el que podrás observar los procesos realizados por log4view y depurar los posibles errores de una manera más sencilla: