C# - Serilog  : Criando logs para console, arquivo e banco de dados


 Neste artigo voltamos a tratar com o Serilog uma biblioteca para registro de diagnósticos, e log para arquivos, e veremos como criar registro de eventos via console, em arquivos texto e json e em um banco de dados SQL Server.

O Serilog é uma biblioteca que você pode usar em aplicações .NET para realizar o logging. Ela é simples, fácil de configurar, tem uma API limpa e é portátil entre plataformas .NET recentes.

Eu já apresentei o Serilog e mostrei como usar alguns dos seus recursos neste artigo:  C# - Usando o Serilog

Neste artigo veremos como criar logs para console, arquivos e para um banco de dados SQL Server de forma bem simples usando o Serilog.

Vamos criar um projeto ASP .NET Core Web API usando o template padrão e neste projeto vamos mostrar como criar os logs definindo as configurações no arquivo appsettings.json.

recursos usados:

Criando a Web API ASP .NET Core

Abra o VS 2019 e clique em Create a New Project

A seguir  e selecione o template ASP .NET Core Web API e clique em Next;

Informe o nome Serilog_Demo e clique em Next;

A seguir selecione o Target Framework, Authentication Type e demais configurações conforme mostrada na figura:

A seguir vamos incluir os seguintes pacotes do Serilog em nosso projeto:

Serilog.AspNetCore
Serilog.Sinks.MSSqlServer
Serilog.Enrichers.Environment
Serilog.Enrichers.Thread
Serilog.Enrichers.Process

Podemos instalar esses pacotes usando o comando : Install-Package <nome> na janela do Package Manager Console.

Configurando o Serilog no arquivo Program

Agora vamos definir o código para configurar o Serilog no arquivo Program.cs do projeto usando o código a seguir:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
namespace Serilog_Demo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var config = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json").Build();
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(config).CreateLogger();
            try
            {
                Log.Information("API Inicializando...");
                CreateHostBuilder(args).Build().Run();
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "A Aplicação falhou a iniciar.");
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Neste código estamos habilitando a leitura do arquivo appsettings.json pois nele vamos criar as definições dos lgos que desejamos criar.  Para isso o Serilog vai ter que ler o arquivo appsettings.json para obter as definições e criar os respectivos logs.

A seguir vamos criar o logger raiz usando o Loogerconfiguration e para isso usamos uma instancia de LoggerConfiguration
e a partir das informações obtidas no arquivo appsettings.json criamos um logger usando as sinks, os enrichers e as demais definições do arquivo appsettings.json.

A seguir definimos o Serilog como provedor de log ao invés de usar o recurso padrão da plataforma .NET.

Definindo as configurações dos logs no arquivo appsettings.json

Agora precisamos definir as configurações dos logs no arquivo appsettings.json. Vamos criar logs no console, em arquivos e em um banco de dados e para isso vamos usar o código a seguir:

{
  "AllowedHosts": "*",
  "Serilog": {
    "Using": [],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "C:\\Dados\\Logs\\log.txt",
          "outputTemplate": "{Timestamp} {Message}{NewLine:1}{Exception:1}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "C:\\Dados\\Logs\\log.json",
          "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
        }
      },
      {
        "Name": "MSSqlServer",
        "Args": {
          "connectionString": "Data .. .Initial Catalog=DemoSerilogDB;Integrated Security=True",
          "sinkOptionsSection": {
            "tableName": "Logs",
            "autoCreateSqlTable": true
          },
          "restrictedToMinimumLevel": "Warning"
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithProcessId",
      "WithThreadId"
    ],
    "Properties": {
      "ApplicationName": "Serilog.WebAPI"
    }
  }
}

Criamos a seção Serilog no arquivo e a seguir usando o método WriteTo definimos 3 tipos de log:

  1. Console
  2. File
  3. MSSqlServer

Em cada definição precisamos informar as definições pertinentes.

Estamos gerando logs para arquivos em dois formatos : texto e JSON.

Para criar o log para o banco de dados SQL Server informamos a string de conexão contendo o nome do banco de dados, o nome da tabela a ser criada e aplicamos o atributo autoCreateSqlTable. Com isso será criada a tabela Logs no banco de dados DemoSerilogDB com a seguinte estrutura padrão:

Assim, agora podemos definir o registro dos logs no controlador WeatherForecast criado por padrão.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Serilog_Demo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase

    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
            _logger.LogInformation("WeatherForecast instanciando ILogger");
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            _logger.LogInformation("endpoint GET -> WeatherForecast.Get() ");
            int count;
            try
            {
                for (count = 0; count <= 5; count++)
                {
                    if (count == 3)
                        throw new Exception("Ocorreu uma Exception Aleatória... ");
                    else
                        _logger.LogInformation($"Número de iterações {count}");
                }
                var rng = new Random();
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = Summaries[rng.Next(Summaries.Length)]
                 })
                .ToArray();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"endpoint GET -> WeatherForecast.Get() - Exception ");
                throw;
            }
        }
    }
}

No método Get do controller WeatherForecast incluímos alguns registros de eventos para o nível information e error.

Para executar o projeto selecione o projeto Serilog_Demo e execute. Veremos a interface do swagger exibir o endpoint GET que quando acionado irá executar o método GET do controller.

Teremos o resultado abaixo:

Agora vamos verificar os logs gerados:

1- Console:

2- Os arquivos log.txt e log.json na pasta c:\dados\Logs

3- O log no banco de dados DemoSerilogDB onde foi criada a tabela Logs com o conteúdo abaixo:

Vimos assim como foi fácil criar logs definindo as configurações no arquivo appsettings.json usando o Serilog.

Pegue o projeto aqui:  Serilog_Demo.zip

"Não me envergonho do evangelho, porque é o poder de Deus para a salvação de todo aquele que crê: primeiro do judeu, depois do grego."
Romanos 1:16

Referências:


José Carlos Macoratti