sábado, 30 de janeiro de 2016

Conhecendo o log4Net

Para conhecer o log4Net há algumas boas referências:

São necessários 5 passos para utilizar o log4net:

1 - Instalar na aplicação o pacote nuget, que pode ser feito via comando no Package Manager Console:

Install-Package log4net

2 - Configurar no app.config ou web.config o log, seguindo a documentação

A vantagem de definir as configurações do log nesses arquivos é poder alterá-las em ambiente de execução, sem necessidade de compilar as soluções
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<!--Para logar no console https://logging.apache.org/log4net/log4net-1.2.13/release/sdk/log4net.Appender.ConsoleAppender.html-->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="ERROR" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] [%logger] %-5level %logger [%ndc] - %message%newline" />
</layout>
</appender>
<!--Para salvar em arquivo https://logging.apache.org/log4net/log4net-1.2.13/release/sdk/log4net.Appender.FileAppender.html-->
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="mylogfile.txt" />
<appendToFile value="false" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] [%logger] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
<!--Para gerenciar maximo e historico de arquivo https://logging.apache.org/log4net/log4net-1.2.13/release/sdk/log4net.Appender.RollingFileAppender.html-->
<appender name ="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="myRollingLogfile.txt"/>
<appendToFile value ="true" />
<rollingStyle value="Size" />
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="5"/>
<staticLogFileName value ="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] [%logger] %level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="FileAppender"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
</configuration>
view raw config hosted with ❤ by GitHub
No elemento <confisections> configuramos que no arquivo haverá a seção para o log4net. No elemento <log4net>definimos a configuração do log.

<root>

O <root> é necessário para definir o nível(level) de log através do elemento (filtrando mensagens de relevância menor que a definida) e há 7 níveis:
  1. OFF - Nada é logado
  2. FATAL
  3. ERROR
  4. WARN
  5. INFO
  6. DEBUG
  7. ALL - Tudo é logado
Por exemplo, se o nível do log for definido para ERROR, somente mensagens de ERROR e FATAL serão armazenadas.
Além disso é necessário adicionar a tag <appender-ref> referenciando os appenders  (Que falaremos abaixo)

No exemplo acima no estou utilizando:
  • ConsoleAppender, ou seja, os logs sao enviados ao Console
  • FileAppender, para salvar em disco (No qual configuerei para salvar somente a última execução com a tag <appendtofile value="false">)




  • RollingFileAppender (Para salvar um histórico de arquivo limitando quantidade e tamanho)

  • Uma propriedade comum que utilizei nesses appenders foram os elementos <layout> e o <conversionpattern>. Há algumas opções interessantes como:
    • timestamp  = Número de milissegundos desde o início da aplicação)
    • %20timestamp = Para garantir que item a ser logado tenha no mínimo 20 caracteres, adicionando espaço. No exemplo acima, fará para o valor do timestamp
    • %property{user} = que podemos definir uma propriedade definida no código

    Para entender todas as demais configurações feitas, sugiro consultar a documentação que está no link de cada appender citado.

    Ainda há várias outras opções de Appenders como podemos ver na documentação.
    Também é possivel customizar appenders, como no exemplo deste link que faz um appender para CSV.

    No vídeo ainda é demonstrado o o AdoNetAppender salvando informações na base de dados.

    3 Aplicar as configurações do app.config

    Ao adicionar essa linha de código(para organizacao, no program.cs abaixo dos using), toda a configuração do log4net será feita lendo o arquivo de configuração (E recarregada em caso de alterações):

    [assembly: log4net.Config.XmlConfigurator(Watch = true)]
    

    Ou para a web:

    4 Configurar a instância

    Para configurar a instância, são indicadas 2 formas:
    1) Se você utilizar a Framework anterior a 4.5, deverá instanciar em toda classe conforme abaixo:
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    view raw cs hosted with ❤ by GitHub
    Dessa forma o log é instanciado por classe e você saberá onde o log foi feito. O parâmetro string que esta sendo passado por reflector facilitar o copiar e colar, mas gera uma pequena perda de desempenho (Ja que a instância estática é criada uma vez por cada classe)


    2) A partir da framework 4.5 é possivel resolver o nome do log em momento de compilacao, utilizando o código abaixo:
    private static readonly log4net.ILog log = LogHelper.GetLogger();
    view raw cs hosted with ❤ by GitHub
    O código do LogHelper está disponível aqui:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading.Tasks;
    namespace Log4NetExample
    {
    public class LogHelper
    {
    /// <summary>
    /// http://www.thomaslevesque.com/2012/06/13/using-c-5-caller-info-attributes-when-targeting-earlier-versions-of-the-net-framework/
    /// https://msdn.microsoft.com/pt-br/library/system.runtime.compilerservices.callerfilepathattribute%28v=vs.110%29.aspx
    /// </summary>
    /// <param name="fileName">Valor definido em momento de compilacao</param>
    /// <returns></returns>
    public static log4net.ILog GetLogger([CallerFilePath] string fileName = "")
    {
    return log4net.LogManager.GetLogger(fileName);
    }
    }
    }
    view raw LogHelper.cs hosted with ❤ by GitHub

    5 Efetuar log

    A parte mais fácil é utilizar o log. Basta utilizar a instância criada na classe e chamar os métodos:
    • Debug()
    • Info()
    • Warn()
    • Error()
    • Fatal()

    O código fonte do exemplo está disponível no GitHub.