ASP.NET Core: Implementando Health Checks e Interfaces Gráficas de Monitoramento

ASP.NET Core: Implementando Health Checks e Interfaces Gráficas de Monitoramento
3 anos atrás

A partir da versão 2.2 do ASP.NET Core, a Microsoft implantou as bibliotecas de Health Check para a ferramenta. Health Checks são mecanismos de validação, para identificar uma instabilidade ou inoperação de um determinado sistema ou ferramenta. Normalmente funcionais a partir de um endpoint HTTP, que retornam um resultado entre Healthy (operante), Degrated (Degradado) ou Unhealthy (inoperante). Em resumo, um middleware fornecido através de um endpoint para comunicação do estado atual da aplicação.

Health Checks são muito úteis e podem ser usados por

  • Orquestradores de contâiner — processo que automatiza e gerencia um grande número de contêineres e como eles interagem entre si;
  • Load Balances — algoritmos ou mecanismos usados ​​para distribuir com eficiência uma solicitação de entrada do servidor ou tráfego entre os servidores do pool de servidores;
  • Service Bus — agente de mensagens empresarial totalmente gerenciado com filas de mensagens e tópicos de publicação/assinatura. O Service Bus é usado para separar aplicativos e serviços uns dos outros;
  • dentre outros serviços que necessitem de uma validação para manter a estabilidade ou saúde da aplicação operando normalmente.

Iniciando nosso projeto

Neste artigo, faremos a inicialização do projeto ASP.NET 5 com o Visual Studio 2019. Mas você pode fazer com a sua IDE de preferência usando o comando: dotnet new webapi --framework net5.0

Abrindo o Visual Studio 2019, vamos iniciar um projeto ASP.NET Core Web API.

Configurando o Startup.cs

O próximo passo, para comportarmos os Health Checks em nossa Web API, é configurar o Startup.cs.

Adicione o serviço ao contêiner de injeção de dependência, utilizando o comando: services.AddHealthChecks();

E também, para configurarmos a rota, utilize: app.UseHealthChecks("/health");

Seu startup precisará ao final das implementações, se manter no seguinte estado:

Abaixo, o código fonte atual do startup.

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHealthChecks();
            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "HealthChecks", Version = "v1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "HealthChecks v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            app.UseHealthChecks("/health");
        }
    }

Primeiros testes de saúde

Neste momento, nossa aplicação já está apta para suportar os middlewares dos Health Checks. Com isto, podemos realizar nosso primeiro teste de saúde. Vamos lá?

Vamos executar nossa aplicação. Como estamos neste artigo utilizando o Visual Studio, apertar F5 já nos trará a execução. Caso esteja utilizando alguma outra IDE ou Command Line, utilize o comando dotnet run.

Nossa aplicação está no ar! Vamos observar a URL criada pelo IIS: localhost:44387. Guarde sua URL para os testes.

Vamos acessar o endpoint que informamos ao nosso Startup.cs. Insira /health após a sua URL.

Recebemos o seguinte retorno: Healthy

Perfeito. Podemos visualizar que o middleware já está executando suas chamadas.

Segundo teste de saúde

Após analisarmos que conseguimos buscar a integridade de nossa API no último teste, precisamos também garantir que conseguiremos saber quando não houver com sucesso a integridade da mesma. Então vamos realizar nosso segundo teste com um banco de dados!

A efeito de exemplo, realizei a criação de um novo banco de dados no Azure.

Você também pode criar um banco de dados local, de sua preferência. Apenas vamos utilizar algum serviço de database para testarmos a funcionalidade.

Database criado. Vamos para a configuração do nosso middleware.

Para inserirmos o suporte à SQL Server, precisamos baixar o pacote AspNetCore.HealthChecks.SqlServer.

Voltando ao nosso Startup.cs, faremos a inserção do trecho de código

        string connectionString = "";
        services.AddHealthChecks().AddSqlServer(connectionString);

Vamos executar nossa API, e analisar o que é retornado.

Após executado, conseguimos o valor que esperávamos, afinal, nossa connectionString está vazia, ou seja, não existe banco! 😱 (Simulando uma indisponibilidade)

Se você inserir sua connectionString corretamente, como na imagem abaixo, pode-se analisar que será encontrado corretamente seu banco de dados. Em resumo, será avisado que está tudo OK. 😉

Interface gráfica

Que tal trabalharmos com uma visualização mais detalhada sobre as nossas análises, utilizando uma forma gráfica? Sem problemas. Utilizando NuGets adicionais do AspNet, nós conseguimos realizar tal feito.

Estes pacotes são:

AspNetCore.HealthChecks.UI, AspNetCore.HealthChecks.UI.Client e AspNetCore.HealthChecks.UI.InMemory.Storage.

Vamos instala-los em nossa aplicação.

Feito.

Adicione os seguintes trechos de código para a inserção e configuração da interface gráfica.

services.AddHealthChecksUI(options =>
{
    options.AddHealthCheckEndpoint("Health Checks", "/health");
    options.SetEvaluationTimeInSeconds(5);
    options.MaximumHistoryEntriesPerEndpoint(10);
})
.AddInMemoryStorage();
  • AddHealthCheckEndpoint() define o endpoint para acessar a interface;
  • SetEvaluationTimeInSeconds() define o intervalo à ser verificado a saúde do nosso serviço;
  • MaximumHistoryEntriesPerEndpoint() define a quantidade de registros por endpoint;

Usamos também um banco de dados em memória, para armazenar todos os históricos (método AddInMemoryStorage).

Por fim, adicionando app.UseHealthChecksUI(options => { options.UIPath = "/report"; }); no método Configure()

Perfeito! Configurados. Vamos testar.

Acesse o endpoint /report e vamos ver funcionando.

Voilá. Aí está nossa aplicação, com validações de Health Checks e uma interface gráfica para visualização dos mesmos, onde cada linha representa uma nova verificação com suas propriedades de data e resultado.

Como explicado, a utilização de Health Checks faz com que sua aplicação tenha mais uma camada de monitoramento. Com a principal vantagem, sua utilização de endpoints para exibição do resultado de saúde, é possível facilmente integrar diversos aplicativos externos que possam depender da alta disponibilidade da solução. É sempre importante ter em mente, uma solução com o plano B para caso algum serviço se encontre fora do ar, e através dos poucos trechos de códigos exibidos neste artigo, é possível fornecer de forma transparente todo o monitoramento necessário e encontrar as devidas ações a partir disto.

É interessante explorar os demais serviços por trás deste middleware super eficaz e muito importante no ciclo de vida de software. Como por exemplo, webhooks, personalização da interface gráfica etc.

Fique à vontade em explorar a documentação Microsoft sobre o mesmo.

Código-fonte deste artigo foi disponibilizado no Github do autor. Verifique: https://github.com/jeffdevalmeida/HealthCheck.Example

Se você gostou do conteúdo, não se esqueça de compartilhar nas redes sociais. Adicione #konianos em sua publicação. ✨

Fonte: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0

Jefferson Almeida

Jefferson Almeida