Serilog e ASP.NET Core: Armazenando logs no SQL Server

Olá, galera! Tudo bem por aí?

O novo artigo, como o título diz, tem como objetivo guiar vocês na configuração e geração de logs de suas aplicações ASP.NET Core para armazenamento no banco de dados SQL Server. Se não conhece o conceito de log, fica tranquilo que vou abordar sobre a definição e do porquê você deve utilizá-lo em suas aplicações.

Código fonte para o exemplo completo aqui.

Vamos lá?

O que são logs e para que utilizar?

Já ocorreu contigo ou em um projeto seu de aparecer um problema em homologação e produção, e você não ter meios de saber o que ocorreu além de dar umas consultas SQL para verificar o estado do objeto? Sei bem como é essa sensação. Frustrante, certo? É como se estivéssemos tateando no escuro.

Bom, para quem não curte ser adivinho, os logs aparecem como uma grande ajuda. Eles representam eventos da aplicação ou infraestrutura.

Quando algum erro ocorre em nossa aplicação, ao invés de incorporarmos o Shazam, podemos analisar o destino de armazenamento desses registros, e entender o que está acontecendo. Esses destinos podem ser arquivos físicos, bancos de dados relacionais, NoSQL, etc.

Além disso, é recomendável utilizar logs junto a uma ferramenta de monitoramento. Afinal, com o tempo, a quantidade de logs vai aumentar consideravelmente, com o custo da busca aumentando na mesma proporção. Além disso, normalmente queremos tomar uma posição ativa na resolução de erros, ao invés de sempre esperar que algum cliente venha reclamar. Com isso, ferramentas de monitoramento nos auxiliam a detectar e agir proativamente.

Serilog

A biblioteca escolhida para o tutorial é o Serilog, por ser uma biblioteca popular, madura e de configuração e sintaxe simples. A sua versão para o ASP.NET Core é o Serilog.AspNetCore. Caso tenha interesse em ler mais além do que vou abordar aqui, recomendo acessar seu wiki no Github.

Níveis

É importante pelo menos citar o conceito de níveis, relacionados aos eventos registrados. Eles formam uma hierarquia de categorias, onde são registrados a partir do mínimo definido. Na ordem de menor para maior, são eles:

  • Verbose: Esse é o nível com maior geração de registros, dificilmente se vê ele habilitado.
  • Debug: Descreve eventos internos do sistema.
  • Information: Registra eventos correspondentes a funções no sistema. Por exemplo quando fazemos uma requisição HTTP a um endpoint da nossa API, logs a respeito dessa requisição serão gerados. 
  • Warning: Indicado para representar quando o sistema apresenta algum comportamento fora dos parâmetros esperados.
  • Error: Utilizado em exceções, por exemplo quando uma funcionalidade está indisponível.
  • Fatal: Representa o nível mais crítico, onde atenção urgente é necessária.

Por exemplo, se o nível mínimo for Information, eventos relativos às categorias de Information, Warning, Error e Fatal serão registrados.

Instalando

Para este tutorial, os pacotes necessários para serem instalados são:

  • Serilog.AspNetCore;
  • Serilog.Sinks.MSSQLServer.

A seguir, coloco os comandos para adicionar ambos os pacotes ao seu projeto. Caso utilize o Visual Studio, basta procurar pelo nome dos pacotes no Gerenciador de Pacotes NuGet.

Instalar pacotes necessários para usar o Serilog com SQL Server

Adicionando logging com Serilog em sua aplicação

Para criarmos registros utilizando no SQL Server utilizando o Serilog, após sua instalação são necessários três passos:

  • Criar a tabela com o schema do registro;
  • Configurar o Serilog no arquivo Program.cs;
  • Chamar o método responsável pela criação do registro.

Vamos ir passo-a-passo agora.

Criando a tabela

O nome do banco de dados definido é ApplicationLogs, e a tabela se chama Logs. O esquema dele está definido na imagem a seguir. Para deixar algo mais “real”, neste tutorial é utilizada uma coluna/propriedade extra, já que muito provavelmente você armazenaria informações além do que a ferramenta registra para você de maneira automática.

Script para criar a tabela a ser utilizada, no SQL Server

Action é a nossa coluna extra. Se você deseja adicionar dados sobre código de usuário, IP, entre outros, você adicionaria nesse script como novas colunas. Você pode encontrar esse código no arquivo script_table_log.sql.

Configurando o Serilog

A configuração do Serilog é feita no arquivo Program.cs. Dentro do método Main, como é mostrado no código abaixo, instanciamos LoggerConfiguration e chamamos métodos de extensão dos dois pacotes instalados anteriormente, visando a configuração a ser utilizada no registro das informações. Dados como nome de tabela, cadeia de conexão e configurações da aplicação são definidas aqui. Caso tenha informações extras, como é o nosso caso, estas devem ser passadas pelo objeto de tipo ColumnOptions.

Configurando o Serilog

Gerando o Log

Para salvar os registros, basta utilizar a classe estática Log (namespace Serilog), e chamar o método correspondente ao nível do Log desejado. Para adicionar valores para propriedades extras que você tenha definido no momento de criar o Logger, utilize o método ForContext, passando como primeiro parâmetro o nome da propriedade, e em seguida o valor.

No nosso exemplo, o evento é registrado no método Get do CatalogosController.

Gerando o log no Controller

Executamos a aplicação, e acessamos o endpoint correspondente. Como é uma operação GET, é suficiente acessarmos a URL pelo navegador.

Resultado do acesso da API

Consultando o registro

Executamos uma consulta simples no banco de dados SQL Server. Neste caso, utilizo a extensão mssql do Visual Studio Code. Vemos a nossa chamada registrando a informação do acesso ao nosso endpoint, com a coluna extra Action preenchida.

A consulta pode ser encontrada no arquivo consultas.sql.

Logs criados no SQL Server

Inscreva-se na lista de espera do Método .NET Direto ao Ponto, um treinamento completo sobre C#, APIs com ASP.NET Core e Microsserviços:  Inscreva-se aqui.

São quase 200 vídeo-aulas sobre temas como C#, ASP NET Core 5, EF Core, CQRS, Clean Architecture, Autenticação e autorização com JWT, Testes Unitários, além de mini-cursos em Microsserviços, Performance em .NET, ASP NET Core e Azure, Docker, Carreira Internacional em .NET, e mais.

Conclusão

Deu para ver quão prático o Serilog é. Com relativamente poucas linhas de código, conseguimos configurar uma aplicação ASP.NET Core para salvar dados em um banco de dados SQL Server, e ainda utilizar um campo de registro personalizado. Lembre-se que outras opções de destino são suportadas por pacotes do Serilog.

Espero que possa agregar em seus projetos. Que tal aplicar em um projeto pessoal, e depois recomendar para algum projeto de sua empresa?

Até a próxima!

Se achou o artigo interessante, te convido a comentar, e/ou compartilhar!

Se tiver idéias de assuntos e/ou tecnologias que queiram que eu aborde em um artigo futuro, não hesite em entrar em contato!