Serilog e .NET Framework com C#

Autor : Antonio Carlos Ferreira de Azevedo
Postado em : 06/10/2023


Serilog e .NET Framework com C

Serilog é uma biblioteca de registro estruturado para .NET. Ele é fácil de configurar, possui uma API limpa e é portátil entre várias plataformas. Vamos ver como configurar o Serilog para um projeto .NET Framework usando C#.

Vantagens do Serilog

O Serilog oferece várias vantagens em relação a outras bibliotecas de registro:

  1. Registro Estruturado: Ao contrário do registro de texto tradicional, o registro estruturado permite que você capture mais informações em um formato que é mais fácil de processar e analisar.

  2. Sinks: Serilog suporta uma ampla variedade de sinks, permitindo que você envie seus logs para quase qualquer lugar, desde arquivos locais até serviços de log remotos.

  3. Integração Fácil: Serilog pode ser facilmente integrado com .NET Framework e .NET Core, e suporta muitos dos mesmos padrões de registro.

  4. Desempenho: Serilog é projetado para ser rápido e eficiente, minimizando o impacto no desempenho do seu aplicativo.

Configuração Inicial

Primeiro, você precisa instalar o pacote NuGet Serilog. Você pode fazer isso através do Gerenciador de Pacotes NuGet ou através da Linha de Comando do Gerenciador de Pacotes com o seguinte comando:

Install-Package Serilog

Depois de instalado, você pode configurar o Serilog no seu arquivo Program.cs ou Startup.cs, dependendo da natureza do seu projeto.

using Serilog;

public class Program
{
    public static void Main()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();

        Log.Information("Hello, Serilog!");

        Log.CloseAndFlush();
    }
}

Neste exemplo, estamos configurando o Serilog para registrar mensagens no console. A chamada Log.CloseAndFlush() garante que todos os eventos pendentes sejam liberados antes que o aplicativo seja encerrado.

Registro Estruturado

Uma das principais vantagens do Serilog é o suporte para registro estruturado. Isso significa que você pode registrar eventos complexos com várias propriedades e o Serilog será capaz de formatá-los de maneira legível ou serializá-los como JSON para armazenamento e análise.

var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;

Log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);

Neste exemplo, @Position e {Elapsed:000} são propriedades estruturadas. O uso do sinal @ instrui o Serilog a serializar a propriedade Position como um objeto estruturado em vez de convertê-lo em uma string.

Sink

Serilog usa algo chamado "sinks" para determinar onde as mensagens de log serão enviadas. No exemplo anterior, usamos o sink do console, mas muitos outros estão disponíveis para coisas como arquivos de texto, bancos de dados SQL e serviços de log remotos.

Para usar um sink diferente, você precisará instalar o pacote NuGet apropriado e então poderá adicioná-lo à sua configuração.

Install-Package Serilog.Sinks.File
Log.Logger = new LoggerConfiguration()
    .WriteTo.File("log.txt")
    .CreateLogger();

Neste exemplo, estamos usando o sink do arquivo para gravar mensagens de log em um arquivo chamado log.txt.

Aqui está um exemplo de como você pode configurar o Serilog para registrar logs em um arquivo ao chamar um endpoint de uma API usando o Serilog.Sinks.File

Configure o Serilog no método Startup do seu aplicativo:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.File("Logs/MeusLogs.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();
    }
}

Aqui, estamos configurando o Serilog para registrar mensagens em um arquivo chamado MeusLogs.txt na pasta Logs. O parâmetro rollingInterval: RollingInterval.Day faz com que o Serilog crie um novo arquivo de log a cada dia.

Agora, você pode usar o Serilog para registrar informações em qualquer lugar do seu aplicativo. Por exemplo, aqui está como você pode registrar informações ao chamar um endpoint de API:

[Route("api/[controller]")]
public class MyController : Controller
{
    [HttpGet]
    public IActionResult Get()
    {
        Log.Information("GET request received for MyController");
        return Ok();
    }
}

Neste exemplo, estamos registrando uma mensagem de informação sempre que o endpoint GET do MyController é chamado. As mensagens de log serão escritas no arquivo myapp.txt.

Lembre-se de chamar Log.CloseAndFlush() no método Dispose ou Shutdown do seu aplicativo para garantir que todos os eventos de log pendentes sejam liberados antes que o aplicativo seja encerrado.

Agora, vamos supor que você fez uma solicitação GET para este endpoint. O conteúdo do arquivo de log MeusLogs.txt seria algo assim:

2023-10-06 14:32:21.123 +00:00 [INF] GET request received for MyController

Aqui está um exemplo de como você pode configurar o Serilog para registrar automaticamente as exceções em um aplicativo C# e gravá-las em um arquivo de texto. Além disso, este exemplo mostra como capturar o payload e o cabeçalho da requisição na entrada do endpoint de uma API.

Configure o Serilog no método Startup do seu aplicativo:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        Log.Logger = new LoggerConfiguration()
            .Enrich.FromLogContext()
            .WriteTo.File("Logs/MeusLogs.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();

        app.Use(async (context, next) =>
        {
            // Captura o payload da requisição
            context.Request.EnableRewind();
            var buffer = new byte[Convert.ToInt32(context.Request.ContentLength)];
            await context.Request.Body.ReadAsync(buffer, 0, buffer.Length);
            var requestBody = Encoding.UTF8.GetString(buffer);
            context.Request.Body.Position = 0;

            // Captura o cabeçalho da requisição
            var requestHeaders = context.Request.Headers;

            Log.Information("Request Headers: {@Headers}", requestHeaders);
            Log.Information("Request Body: {@Body}", requestBody);

            await next.Invoke();
        });

        // Restante da configuração do aplicativo aqui
    }
}

Neste exemplo, estamos usando um middleware personalizado com app.Use para capturar o payload e o cabeçalho da requisição. As informações capturadas são então registradas usando o Serilog.

Aqui está um exemplo prático de como você pode usar a propriedade {@Client} com o Serilog para serializar um objeto:

public class Client
{
    public int ClientId { get; set; }
    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .CreateLogger();

        var client = new Client { ClientId = 1, Name = "John Doe" };

        Log.Information("Processed {@Client}", client);

        Log.CloseAndFlush();
    }
}

Neste exemplo, temos uma classe Client com propriedades ClientId e Name. Criamos uma instância dessa classe e a passamos para o método Log.Information com a propriedade estruturada {@Client}.

Quando este código é executado, ele produzirá uma saída semelhante a esta:

2023-10-06 14:32:21.123 +00:00 [INF] Processed {"ClientId": 1, "Name": "John Doe"}

Como você pode ver, a propriedade {@Client} instrui o Serilog a serializar o objeto client como um objeto estruturado em vez de convertê-lo em uma string. Isso permite que você capture mais informações em seus logs e as analise mais facilmente mais tarde.

Aqui está um exemplo de como você pode usar o Serilog para capturar o rastreamento de uma exceção:

try
{
    // Código que pode lançar uma exceção aqui
}
catch (Exception ex)
{
    Log.Error(ex, "Ocorreu uma exceção.");
}

Neste exemplo, qualquer exceção lançada dentro do bloco try será capturada e passada para o método Log.Error. O Serilog automaticamente incluirá o rastreamento da exceção no log.

A saída do log será semelhante a isto:

2023-10-06 14:32:21.123 +00:00 [ERR] Ocorreu uma exceção.
System.NullReferenceException: Object reference not set to an instance of an object.
   at Program.Main() in C:\path\to\your\program.cs:line 14

Como você pode ver, a saída inclui a mensagem de erro, o tipo de exceção, a mensagem da exceção e o rastreamento da pilha, que mostra onde a exceção ocorreu no código.

Global.asax

Para configurar o Serilog em Global.asax, capturar o cabeçalho e o payload da requisição, e registrar as mensagens em um arquivo chamado MeusLogs.txt, você pode fazer o seguinte:

Configure o Serilog no método Application_Start do seu aplicativo:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.File("MeusLogs.txt")
            .CreateLogger();

        Log.Information("Aplicação iniciada.");
    }
}

Aqui, estamos configurando o Serilog para registrar mensagens em um arquivo chamado MeusLogs.txt.

Para capturar o cabeçalho e o payload da requisição, você pode adicionar um middleware personalizado ao pipeline do seu aplicativo. Aqui está um exemplo de como você pode fazer isso:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_BeginRequest()
    {
        var request = HttpContext.Current.Request;
        var headers = request.Headers;
        var inputStream = request.InputStream;
        inputStream.Position = 0;
        var payload = new StreamReader(inputStream).ReadToEnd();

        Log.Information("Headers: {@Headers}", headers);
        Log.Information("Payload: {@Payload}", payload);

        inputStream.Position = 0; // Redefina a posição do InputStream para o início para processamento adicional nas etapas subsequentes do pipeline.
    }
}

Neste exemplo, estamos capturando o cabeçalho e o payload da requisição no evento BeginRequest e registrando-os usando o Serilog.

Finalmente, certifique-se de chamar Log.CloseAndFlush() no método Application_End para garantir que todos os eventos pendentes sejam liberados antes que o aplicativo seja encerrado.

protected void Application_End()
{
    Log.Information("Aplicação encerrada.");
    Log.CloseAndFlush();
}

Métodos

Serilog fornece uma série de métodos para registrar mensagens de log em diferentes níveis. Aqui estão alguns dos mais comuns:

  1. Log.Verbose(): Este método é usado para registrar mensagens que são detalhadas e geralmente apenas úteis durante o desenvolvimento e depuração². Por exemplo, Log.Verbose("This is a verbose message."); registrará a mensagem "This is a verbose message." no nível Verbose².

  2. Log.Debug(): Este método é usado para registrar mensagens que são úteis para depuração². Por exemplo, Log.Debug("This is a debug message."); registrará a mensagem "This is a debug message." no nível Debug².

  3. Log.Information(): Este método é usado para registrar mensagens informativas que descrevem o fluxo normal de operação de um aplicativo². Por exemplo, Log.Information("This is an information message."); registrará a mensagem "This is an information message." no nível Information².

  4. Log.Warning(): Este método é usado para registrar mensagens que indicam uma situação potencialmente prejudicial². Por exemplo, Log.Warning("This is a warning message."); registrará a mensagem "This is a warning message." no nível Warning².

  5. Log.Error(): Este método é usado para registrar mensagens que indicam um erro que impede o aplicativo de funcionar corretamente². Por exemplo, Log.Error("This is an error message."); registrará a mensagem "This is an error message." no nível Error².

  6. Log.Fatal(): Este método é usado para registrar mensagens que indicam um erro crítico que resulta na parada do aplicativo². Por exemplo, Log.Fatal("This is a fatal error message."); registrará a mensagem "This is a fatal error message." no nível Fatal².

Espero que isso ajude! Se você tiver mais perguntas, sinta-se à vontade para perguntar.

Referência

  1. Serilog Tutorial - Structured Blog. https://blog.datalust.co/serilog-tutorial/.
  2. Serilog Tutorial for .NET Logging: 16 Best Practices and Tips - Stackify. https://stackify.com/serilog-tutorial-net-logging/.
  3. Serilog C# (CSharp) Code Examples - HotExamples. https://csharp.hotexamples.com/examples/-/Serilog/-/php-serilog-class-examples.html.
  4. How To Start Logging With Serilog | Better Stack Community. https://betterstack.com/community/guides/logging/how-to-start-logging-with-serilog/.

Espero que este artigo tenha lhe dado uma boa introdução ao uso do Serilog em um projeto .NET Framework com C#. O Serilog é uma ferramenta poderosa e flexível que pode tornar seu registro muito mais útil e gerenciável.



Links Relacionados



Comentários