Verificações de integridade no ASP.NET Core

Por Glenn Condron

o ASP.NET Core oferece middleware de verificações de integridade e bibliotecas para relatar a integridade dos componentes de infraestrutura de aplicativo.

As verificações de integridade são expostas por um aplicativo como pontos de extremidade HTTP. Os pontos de extremidade de verificação de integridade podem ser configurados para uma variedade de cenários de monitoramento em tempo real:

  • As investigações de integridade podem ser usadas por orquestradores de contêineres e balanceadores de carga para verificar o status de um aplicativo. Por exemplo, um orquestrador de contêineres pode responder a uma verificação de integridade com falha interrompendo uma implantação sem interrupção ou reiniciando um contêiner. Um balanceador de carga pode reagir a um aplicativo não íntegro encaminhando o tráfego para fora da instância com falha para uma instância íntegra.
  • O uso de memória, disco e outros recursos de servidor físico pode ser monitorado quanto ao status de integridade.
  • As verificações de integridade podem testar as dependências do aplicativo, como bancos de dados e pontos de extremidade de serviço externo, para confirmar a disponibilidade e o funcionamento normal.

Exibir ou baixar código de exemplo (como baixar)

O aplicativo de exemplo inclui exemplos dos cenários descritos neste tópico. Para executar o aplicativo de exemplo para determinado cenário, use o comando dotnet run na pasta do projeto em um shell de comando. Consulte o arquivo do aplicativo de exemplo README.md e as descrições de cenário neste tópico para obter detalhes sobre como usar o aplicativo de exemplo.

Pré-requisitos

As verificações de integridade são normalmente usadas com um orquestrador de contêineres ou um serviço de monitoramento externo para verificar o status de um aplicativo. Antes de adicionar verificações de integridade a um aplicativo, decida qual sistema de monitoramento será usado. O sistema de monitoramento determina quais tipos de verificações de integridade serão criados e como configurar seus pontos de extremidade.

o Microsoft.AspNetCore.Diagnostics.HealthChecks pacote é referenciado implicitamente para aplicativos ASP.NET Core. Para executar verificações de integridade usando Entity Framework Core, adicione uma referência ao Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore pacote.

O aplicativo de exemplo fornece um código de inicialização para demonstrar verificações de integridade para vários cenários. O cenário de investigação do banco de dados verifica a integridade de uma conexão de banco de dados usando AspNetCore.Diagnostics.HealthChecks . O cenário investigação de DbContext verifica um banco de dados usando um DbContext do EF Core. Para explorar os cenários de banco de dados, o aplicativo de exemplo:

Observação

AspNetCore.Diagnostics.HealthChecks Não é mantido nem tem suporte da Microsoft.

Outro cenário de verificação de integridade demonstra como filtrar verificações de integridade para uma porta de gerenciamento. O aplicativo de exemplo exige que você crie um Properties/launchSettings.json arquivo que inclui a URL de gerenciamento e a porta de gerenciamento. Para obter mais informações, confira a seção Filtrar por porta.

Investigação de integridade básica

Para muitos aplicativos, uma configuração básica de investigação de integridade que relata a disponibilidade do aplicativo para processar solicitações (atividade) é suficiente para descobrir o status do aplicativo.

A configuração básica registra serviços de verificação de integridade e chama o middleware de verificações de integridade para responder em um ponto de extremidade de URL com uma resposta de integridade. Por padrão, nenhuma verificação de integridade específica é registrada para testar qualquer dependência ou subsistema específico. O aplicativo é considerado íntegro se consegue responder na URL do ponto de extremidade de integridade. O gravador de resposta padrão grava o status ( HealthStatus ) como uma resposta de texto não criptografado para o cliente, indicando um HealthStatus.Healthy HealthStatus.Degraded HealthStatus.Unhealthy status ou.

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Crie um ponto de extremidade de verificação de integridade chamando MapHealthChecks em Startup.Configure .

No aplicativo de exemplo, o ponto de extremidade de verificação de integridade é criado em /health ( BasicStartup.cs ):

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHealthChecks("/health");
        });
    }
}

Para executar o cenário de configuração básica usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario basic

Exemplo do Docker

O Docker oferece uma diretiva HEALTHCHECK interna que pode ser usada para verificar o status de um aplicativo que usa a configuração básica de verificação de integridade:

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

Criar verificações de integridade

As verificações de integridade são criadas pela implementação da interface IHealthCheck. O método CheckHealthAsync retorna um HealthCheckResult que indica a integridade como Healthy, Degraded ou Unhealthy. O resultado é gravado como uma resposta de texto sem formatação com um código de status configurável (a configuração é descrita na seção Opções de verificação de integridade). HealthCheckResult também pode retornar pares chave-valor opcionais.

A classe a seguir ExampleHealthCheck demonstra o layout de uma verificação de integridade. A lógica de verificações de integridade é colocada no CheckHealthAsync método. O exemplo a seguir define uma variável fictícia, healthCheckResultHealthy , para true . Se o valor de healthCheckResultHealthy for definido como false , o HealthCheckRegistration.FailureStatus status será retornado.

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(context.Registration.FailureStatus, 
            "An unhealthy result."));
    }
}

Se o CheckHealthAsync lançar uma exceção durante a verificação, um novo HealthReportEntry será retornado com seu HealthReportEntry.Status definido como o FailureStatus , que é definido por AddCheck (consulte a seção registrar serviços de verificação de integridade ) e inclui a exceção interna que inicialmente causou a falha de verificação. O Description é definido como a mensagem da exceção.

Registrar os serviços de verificação de integridade

O ExampleHealthCheck tipo é adicionado aos serviços de verificação de integridade com AddCheck em Startup.ConfigureServices :

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

A sobrecarga AddCheck mostrada no exemplo a seguir define o status de falha (HealthStatus) como relatório quando a verificação de integridade relata uma falha. Se o status de falha for definido como null (padrão), HealthStatus.Unhealthy será relatado. Essa sobrecarga é um cenário útil para autores de biblioteca, em que o status de falha indicado pela biblioteca é imposto pelo aplicativo quando uma falha de verificação de integridade ocorre se a implementação da verificação de integridade respeita a configuração.

Marcas podem ser usadas para filtrar as verificações de integridade (descritas posteriormente na seção Filtrar verificações de integridade).

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck também pode executar uma função lambda. No seguinte exemplo, o nome da verificação de integridade é especificado como Example e a verificação sempre retorna um estado íntegro:

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

Chame AddTypeActivatedCheck para passar argumentos para uma implementação de verificação de integridade. No exemplo a seguir, TestHealthCheckWithArgs aceita um inteiro e uma cadeia de caracteres para uso quando CheckHealthAsync é chamado:

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        ...
    }
}

TestHealthCheckWithArgs é registrado chamando AddTypeActivatedCheck com o inteiro e a cadeia de caracteres passada para a implementação:

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

Usar roteamento de verificações de integridade

No Startup.Configure , chame MapHealthChecks no construtor de ponto de extremidade com a URL do ponto de extremidade ou o caminho relativo:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

Exigir host

Chame RequireHost para especificar um ou mais hosts permitidos para o ponto de extremidade de verificação de integridade. Os hosts devem ser Unicode em vez de Punycode e podem incluir uma porta. Se uma coleção não for fornecida, qualquer host será aceito.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

Para obter mais informações, confira a seção Filtrar por porta.

Exigir autorização

Chame RequireAuthorization para executar o middleware de autorização no ponto de extremidade de solicitação de verificação de integridade. Uma RequireAuthorization sobrecarga aceita uma ou mais políticas de autorização. Se uma política não for fornecida, a política de autorização padrão será usada.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

Habilitar o CORS (Solicitações Entre Origens)

Embora a execução manual de verificações de integridade de um navegador não seja um cenário de uso comum, o middleware CORS pode ser habilitado chamando os RequireCors pontos de extremidade de verificações de integridade. Uma RequireCors sobrecarga aceita um delegado do construtor de política CORS ( CorsPolicyBuilder ) ou um nome de política. Se uma política não for fornecida, a política CORS padrão será usada. Para obter mais informações, consulte Habilitar as solicitações entre origens (CORS) no ASP.NET Core.

Opções de verificação de integridade

HealthCheckOptions oferece uma oportunidade de personalizar o comportamento de verificação de integridade:

Filtrar verificações de integridade

Por padrão, o middleware de verificações de integridade executa todas as verificações de integridade registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que retorne um booliano para a opção Predicate. No seguinte exemplo, a verificação de integridade Bar é filtrada por sua marca (bar_tag) na instrução condicional da função, em que true só é retornado se a propriedade Tags da verificação de integridade corresponde a foo_tag ou baz_tag:

Em Startup.ConfigureServices:

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

No Startup.Configure , o Predicate filtra a verificação de integridade da ' barra '. Somente foo e Baz são executados.:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

Personalizar o código de status HTTP

Use ResultStatusCodes para personalizar o mapeamento de status da integridade para códigos de status HTTP. As atribuições StatusCodes a seguir são os valores padrão usados pelo middleware. Altere os valores do código de status de acordo com suas necessidades.

Em Startup.Configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

Suprimir os cabeçalhos de cache

AllowCachingResponses controla se o middleware de verificações de integridade adiciona cabeçalhos HTTP a uma resposta de investigação para evitar o cache de resposta. Se o valor é false (padrão), o middleware define ou substitui os cabeçalhos Cache-Control, Expires e Pragma para prevenir o cache de resposta. Se o valor é true, o middleware não modifica os cabeçalhos de cache da resposta.

Em Startup.Configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = false
    });
});

Personalizar a saída

No Startup.Configure , defina a HealthCheckOptions.ResponseWriter opção como um delegado para gravar a resposta:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

O delegado padrão grava uma resposta de texto sem formatação mínima com o valor de cadeia de caracteres de HealthReport.Status . Os delegados personalizados a seguir geram uma resposta JSON personalizada.

O primeiro exemplo do aplicativo de exemplo demonstra como usar System.Text.Json :

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ?? 
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

O segundo exemplo demonstra como usar Newtonsoft.Json :

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

No aplicativo de exemplo, comente a SYSTEM_TEXT_JSON diretiva de pré-processador no CustomWriterStartup.cs para habilitar a Newtonsoft.Json versão do WriteResponse .

A API de verificações de integridade não fornece suporte interno para formatos de retorno JSON complexos porque o formato é específico à sua escolha de sistema de monitoramento. Personalize a resposta nos exemplos anteriores, conforme necessário. Para obter mais informações sobre serialização JSON com System.Text.Json , consulte como serializar e desserializar JSON no .net.

Investigação de banco de dados

Uma verificação de integridade pode especificar uma consulta de banco de dados a ser executada como um teste booliano para indicar se o banco de dados está respondendo normalmente.

o aplicativo de exemplo usa AspNetCore.Diagnostics.HealthChecks , uma biblioteca de verificação de integridade para aplicativos ASP.NET Core, para executar uma verificação de integridade em um banco de dados SQL Server. O AspNetCore.Diagnostics.HealthChecks executa uma consulta SELECT 1 no banco de dados para confirmar se a conexão ao banco de dados está íntegra.

Aviso

Ao verificar uma conexão de banco de dados com uma consulta, escolha uma consulta que retorne rapidamente. A abordagem de consulta corre o risco de sobrecarregar o banco de dados e prejudicar o desempenho. Na maioria dos casos, a execução de uma consulta de teste não é necessária. É suficiente apenas estabelecer uma conexão bem-sucedida ao banco de dados. Se você achar necessário executar uma consulta, escolha uma consulta SELECT simples, como SELECT 1.

Inclua uma referência de pacote para AspNetCore.HealthChecks.SqlServer .

Forneça uma cadeia de conexão de banco de dados válida no appsettings.json arquivo do aplicativo de exemplo. O aplicativo usa um banco de dados do SQL Server chamado HealthCheckSample:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. O aplicativo de exemplo chama o AddSqlServer método com a cadeia de conexão do banco de dados ( DbHealthStartup.cs ):

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

Um ponto de extremidade de verificação de integridade é criado chamando MapHealthChecks em Startup.Configure :

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

Para executar o cenário de investigação de banco de dados usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario db

Observação

AspNetCore.Diagnostics.HealthChecks Não é mantido nem tem suporte da Microsoft.

Investigação de DbContext do Entity Framework Core

A verificação DbContext confirma se o aplicativo pode se comunicar com o banco de dados configurado para um DbContext do EF Core. A verificação DbContext é compatível em aplicativos que:

AddDbContextCheck<TContext> registra uma verificação de integridade para um DbContext. O DbContext é fornecido como o TContext para o método. Uma sobrecarga está disponível para configurar o status de falha, marcas e uma consulta de teste personalizada.

Por padrão:

  • o DbContextHealthCheck chama o método CanConnectAsync do EF Core. Você pode personalizar qual operação é executada durante a verificação de integridade usando sobrecargas do método AddDbContextCheck.
  • O nome da verificação de integridade é o nome do tipo TContext.

No aplicativo de exemplo, AppDbContext é fornecido AddDbContextCheck e registrado como um serviço no Startup.ConfigureServices ( DbContextHealthStartup.cs ):

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

Um ponto de extremidade de verificação de integridade é criado chamando MapHealthChecks em Startup.Configure :

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

Para executar o cenário de investigação DbContext usando o aplicativo de exemplo, confirme se o banco de dados especificado pela cadeia de conexão não existe na instância do SQL Server. Se o banco de dados existir, exclua-o.

Execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario dbcontext

Depois que o aplicativo estiver em execução, verifique o status da integridade fazendo uma solicitação para o ponto de extremidade /health em um navegador. O banco de dados e AppDbContext não existem e, portanto, o aplicativo fornece a seguinte resposta:

Unhealthy

Dispare o aplicativo de exemplo para criar o banco de dados. Faça uma solicitação para /createdatabase. O aplicativo responde:

Creating the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O banco de dados e o contexto existem e, portanto, o aplicativo responde:

Healthy

Dispare o aplicativo de exemplo para excluir o banco de dados. Faça uma solicitação para /deletedatabase. O aplicativo responde:

Deleting the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O aplicativo fornece uma resposta não íntegra:

Unhealthy

Investigações de preparação e atividade separadas

Em alguns cenários de hospedagem, é usado um par de verificações de integridade que distingue dois estados de aplicativo:

  • A preparação indica se o aplicativo está em execução normalmente, mas não está pronto para receber solicitações.
  • A vida indica se um aplicativo falhou e deve ser reiniciado.

Considere o exemplo a seguir: um aplicativo deve baixar um arquivo de configuração grande antes de estar pronto para processar solicitações. Não queremos que o aplicativo seja reiniciado se o download inicial falhar, pois o aplicativo pode tentar baixar o arquivo várias vezes. Usamos uma investigação de tempo de vida para descrever a vida do processo, nenhuma verificação adicional é executada. Também queremos impedir que solicitações sejam enviadas ao aplicativo antes que o download do arquivo de configuração seja bem-sucedido. Usamos uma investigação de prontidão para indicar um estado "não pronto" até que o download seja bem sucedido e o aplicativo esteja pronto para receber solicitações.

O aplicativo de exemplo contém uma verificação de integridade para relatar a conclusão da tarefa de inicialização de execução longa em um Serviço Hospedado. O StartupHostedServiceHealthCheck expõe uma propriedade, StartupTaskCompleted , que o serviço hospedado pode definir true quando sua tarefa de execução longa é concluída ( StartupHostedServiceHealthCheck.cs ):

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

A tarefa em segundo plano de execução longa é iniciada por um serviço hospedado ( Services/StartupHostedService ). Após a conclusão da tarefa, StartupHostedServiceHealthCheck.StartupTaskCompleted é definido como true:

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger, 
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

A verificação de integridade é registrada em AddCheck no Startup.ConfigureServices juntamente com o serviço hospedado. Como o serviço hospedado deve definir a propriedade na verificação de integridade, a verificação de integridade também é registrada no contêiner de serviço ( LivenessProbeStartup.cs ):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

Um ponto de extremidade de verificação de integridade é criado chamando MapHealthChecks em Startup.Configure . No aplicativo de exemplo, os pontos de extremidade de verificação de integridade são criados em:

  • /health/ready para a verificação de preparação. A verificação de preparação filtra as verificações de integridade para a verificação de integridade com a marca ready.
  • /health/live para a verificação de tempo de vida. A verificação de vida filtra o StartupHostedServiceHealthCheck retornando false no HealthCheckOptions.Predicate (para obter mais informações, consulte Filtrar verificações de integridade)

No código de exemplo a seguir:

  • A verificação de preparação usa todas as verificações registradas com a marca ' Ready '.
  • O Predicate exclui todas as verificações e retorna um 200-OK.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

Para executar o cenário de configuração de preparação/atividade usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario liveness

Em um navegador, visite /health/ready várias vezes até terem decorrido 15 segundos. A verificação de integridade relata Unhealthy para os primeiros 15 segundos. Após 15 segundos, o ponto de extremidade relata Healthy, que reflete a conclusão da tarefa de execução longa pelo serviço hospedado.

Este exemplo também cria um Publicador de Verificação de Integridade (implementação IHealthCheckPublisher) que executa a primeira verificação de preparação com um atraso de dois segundos. Para saber mais, confira a seção Publicador de Verificação de Integridade.

Exemplo do Kubernetes

O uso de verificações de preparação e atividade separadas é útil em um ambiente como o Kubernetes. No Kubernetes, um aplicativo pode precisar executar um trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade do banco de dados subjacente. O uso de verificações separadas permite que o orquestrador distinga se o aplicativo está funcionando, mas ainda não está pronto, ou se o aplicativo falhou ao ser iniciado. Para obter mais informações sobre as investigações de preparação e atividade no Kubernetes, confira Configurar investigações de preparação e atividade na documentação do Kubernetes.

O seguinte exemplo demonstra uma configuração de investigação de preparação do Kubernetes:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

Investigação baseada em métrica com um gravador de resposta personalizada

O aplicativo de exemplo demonstra uma verificação de integridade da memória com um gravador de resposta personalizada.

MemoryHealthCheck relata um estado degradado se o aplicativo usa mais de determinado limite de memória (1 GB no aplicativo de exemplo). O HealthCheckResult inclui informações do GC (Coletor de Lixo) para o aplicativo ( MemoryHealthCheck.cs ):

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ? 
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Em vez de permitir a verificação de integridade passando-a para AddCheck, a MemoryHealthCheck é registrada como um serviço. Todos os serviços registrados da IHealthCheck estão disponíveis para os serviços de verificação de integridade e middleware. Recomendamos registrar os serviços de verificação de integridade como serviços Singleton.

No CustomWriterStartup.cs do aplicativo de exemplo:

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

Um ponto de extremidade de verificação de saúde é criado chamando MapHealthChecks em Startup.Configure . Um delegado é fornecido à propriedade <Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions.ResponseWriter> para a saída de uma resposta JSON personalizada quando a verificação de saúde é WriteResponse executada:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

O WriteResponse delegado formatará o CompositeHealthCheckResult em um objeto JSON e produzirá a saída JSON para a resposta de verificação de saúde. Para obter mais informações, consulte a seção Personalizar saída.

Para executar a investigação baseada em métrica com a saída do gravador de resposta personalizada usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario writer

Observação

AspNetCore.Diagnostics.HealthChecks inclui cenários de verificação de saúde baseados em métrica, incluindo o armazenamento em disco e verificações de desempenho de valor máximo.

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Filtrar por porta

Chame com um padrão de URL que especifica uma porta para restringir solicitações de verificação RequireHost de saúde à porta MapHealthChecks especificada. Isso normalmente é usado em um ambiente de contêiner para expor uma porta para os serviços de monitoramento.

O aplicativo de exemplo configura a porta usando o Provedor de Configuração de Variáveis de Ambiente. A porta é definida no arquivo launchSettings.json e passada para o provedor de configuração por meio de uma variável de ambiente. Você também precisa configurar o servidor para escutar as solicitações na porta de gerenciamento.

Para usar o aplicativo de exemplo para demonstrar a configuração da porta de gerenciamento, crie launchSettings.json o arquivo em uma Properties pasta.

O seguinte arquivo no aplicativo de exemplo não está incluído nos arquivos de projeto do aplicativo de exemplo e Properties/launchSettings.json deve ser criado manualmente:

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Crie um ponto de extremidade de verificação de saúde chamando MapHealthChecks em Startup.Configure .

No aplicativo de exemplo, uma chamada para no ponto de extremidade em especifica a RequireHost porta de gerenciamento da Startup.Configure configuração:

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

Os pontos de extremidade são criados no aplicativo de exemplo no Startup.Configure . No código de exemplo a seguir:

  • A verificação de preparação usa todas as verificações registradas com a marca 'ready'.
  • O Predicate exclui todas as verificações e retorna um 200-OK.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

Observação

Você pode evitar a criação do arquivo no aplicativo de exemplo definindo a porta launchSettings.json de gerenciamento explicitamente no código. No local em que o é criado, adicione uma chamada para e forneça o ponto de extremidade da Program.cs porta de gerenciamento do HostBuilder ListenAnyIP aplicativo. No Configure de ManagementPortStartup.cs , especifique a porta de gerenciamento com RequireHost :

Program.cs:

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

Para executar o cenário de configuração de porta de gerenciamento usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario port

Distribuir uma biblioteca de verificação de integridade

Para distribuir uma verificação de integridade como uma biblioteca:

  1. Escreva uma verificação de integridade que implementa a interface IHealthCheck como uma classe autônoma. A classe pode depender da DI (injeção de dependência), da ativação de tipo e das opções nomeadas para acessar os dados de configuração.

    Na lógica de verificações de saúde de CheckHealthAsync :

    • data1 e data2 são usados no método para executar a lógica de verificação de saúde da investigação.
    • AccessViolationException é tratado.

    Quando um ocorre, o é retornado com o para permitir que os usuários configurem o status de falha AccessViolationException FailureStatus das HealthCheckResult verificações de saúde.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. Escreva um método de extensão com parâmetros que o aplicativo de consumo chama em seu método Startup.Configure. No seguinte exemplo, suponha a seguinte assinatura de método de verificação de integridade:

    ExampleHealthCheck(string, string, int )
    

    A assinatura anterior indica que a ExampleHealthCheck exige dados adicionais para processar a lógica de investigação de verificação de integridade. Os dados são fornecidos para o representante usado para criar a instância de verificação de integridade quando a verificação de integridade é registrada em um método de extensão. No seguinte exemplo, o chamador especifica itens opcionais:

    • nome da verificação de integridade (name). Se null, example_health_check é usado.
    • ponto de dados de cadeia de caracteres para a verificação de integridade (data1).
    • ponto de dados de inteiro para a verificação de integridade (data2). Se null, 1 é usado.
    • status de falha (HealthStatus). O padrão é null. Se null , será relatado para um status de HealthStatus.Unhealthy falha.
    • marcas (IEnumerable<string>).
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

Publicador de Verificação de Integridade

Quando um IHealthCheckPublisher é adicionado ao contêiner de serviços, o sistema de verificação de integridade periodicamente executa sua verificação de integridade e chama PublishAsync com o resultado. Isso é útil em um cenário de sistema de monitoramento de integridade baseada em push que espera que cada processo chame o sistema de monitoramento periodicamente para determinar a integridade.

A interface IHealthCheckPublisher tem um único método:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions permite que você defina:

  • Delay: o atraso inicial aplicado depois que o aplicativo é iniciado antes de executar IHealthCheckPublisher instâncias. O atraso é aplicado uma vez na inicialização e não ocorre em iterações subsequentes. O valor padrão é cinco segundos.
  • Period: o período de IHealthCheckPublisher execução. O valor padrão é 30 segundos.
  • Predicate: se Predicate for null (padrão), o serviço publicador de verificação de saúde executa todas as verificações de saúde registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que filtre o conjunto de verificações. O predicado é avaliado a cada período.
  • Timeout: o tempo de execução das verificações de saúde para todas IHealthCheckPublisher as instâncias. Use InfiniteTimeSpan para executar sem um tempo limite. O valor padrão é 30 segundos.

No aplicativo de exemplo, ReadinessPublisher é uma implementação IHealthCheckPublisher. O status da verificação de saúde é registrado para cada verificação em um nível de log de:

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks 
    // Middleware already logs health checks results. A real-world readiness 
    // check in a production app might perform a set of more expensive or 
    // time-consuming checks to determine if other resources are responding 
    // properly.
    public Task PublishAsync(HealthReport report, 
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

No exemplo LivenessProbeStartup do aplicativo de amostra, a verificação de preparação StartupHostedService tem um atraso de inicialização de dois segundos, e executa a verificação a cada 30 segundos. Para ativar a implementação IHealthCheckPublisher, o exemplo registra ReadinessPublisher como um serviço singleton no contêiner DI (injeção de dependência):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

Observação

AspNetCore.Diagnostics.HealthChecksinclui publicações para vários sistemas, incluindo Aplicativos Insights.

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Restringir verificações de integridade com MapWhen

Use MapWhen para ramificar condicionalmente o pipeline de solicitação para pontos de extremidade de verificação de integridade.

No exemplo a seguir, ramifica o pipeline de solicitação para ativar o Middleware de Verificações de Integridade se uma MapWhen solicitação GET for recebida para o api/HealthCheck ponto de extremidade:

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

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

Para obter mais informações, consulte Middleware do ASP.NET Core.

ASP.NET Core oferece middleware de verificações de saúde e bibliotecas para relatar a saúde dos componentes de infraestrutura de aplicativo.

As verificações de integridade são expostas por um aplicativo como pontos de extremidade HTTP. Os pontos de extremidade de verificação de integridade podem ser configurados para uma variedade de cenários de monitoramento em tempo real:

  • As investigações de integridade podem ser usadas por orquestradores de contêineres e balanceadores de carga para verificar o status de um aplicativo. Por exemplo, um orquestrador de contêineres pode responder a uma verificação de integridade com falha interrompendo uma implantação sem interrupção ou reiniciando um contêiner. Um balanceador de carga pode reagir a um aplicativo não íntegro encaminhando o tráfego para fora da instância com falha para uma instância íntegra.
  • O uso de memória, disco e outros recursos de servidor físico pode ser monitorado quanto ao status de integridade.
  • As verificações de integridade podem testar as dependências do aplicativo, como bancos de dados e pontos de extremidade de serviço externo, para confirmar a disponibilidade e o funcionamento normal.

Exibir ou baixar código de exemplo (como baixar)

O aplicativo de exemplo inclui exemplos dos cenários descritos neste tópico. Para executar o aplicativo de exemplo para determinado cenário, use o comando dotnet run na pasta do projeto em um shell de comando. Consulte o arquivo do aplicativo de exemplo e as descrições do cenário neste tópico para obter detalhes README.md sobre como usar o aplicativo de exemplo.

Pré-requisitos

As verificações de integridade são normalmente usadas com um orquestrador de contêineres ou um serviço de monitoramento externo para verificar o status de um aplicativo. Antes de adicionar verificações de integridade a um aplicativo, decida qual sistema de monitoramento será usado. O sistema de monitoramento determina quais tipos de verificações de integridade serão criados e como configurar seus pontos de extremidade.

O Microsoft.AspNetCore.Diagnostics.HealthChecks pacote é referenciado implicitamente para ASP.NET Core aplicativos. Para executar verificações de Entity Framework Core, adicione uma referência de pacote ao Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore pacote.

O aplicativo de exemplo fornece um código de inicialização para demonstrar verificações de integridade para vários cenários. O cenário de investigação de banco de dados verifica a saúde de uma conexão de banco de dados usando AspNetCore.Diagnostics.HealthChecks . O cenário investigação de DbContext verifica um banco de dados usando um DbContext do EF Core. Para explorar os cenários de banco de dados, o aplicativo de exemplo:

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Outro cenário de verificação de integridade demonstra como filtrar verificações de integridade para uma porta de gerenciamento. O aplicativo de exemplo exige que você crie um arquivo que inclua a URL de gerenciamento e a Properties/launchSettings.json porta de gerenciamento. Para obter mais informações, confira a seção Filtrar por porta.

Investigação de integridade básica

Para muitos aplicativos, uma configuração básica de investigação de integridade que relata a disponibilidade do aplicativo para processar solicitações (atividade) é suficiente para descobrir o status do aplicativo.

A configuração básica registra os serviços de verificação de saúde e chama o Middleware de Verificações de Saúde para responder em um ponto de extremidade de URL com uma resposta de saúde. Por padrão, nenhuma verificação de integridade específica é registrada para testar qualquer dependência ou subsistema específico. O aplicativo é considerado íntegro se consegue responder na URL do ponto de extremidade de integridade. O autor de resposta padrão grava o status ( ) como uma resposta de texto não criptografado de volta para o cliente, indicando um HealthStatus HealthStatus.Healthy status , ou HealthStatus.Degraded HealthStatus.Unhealthy .

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Crie um ponto de extremidade de verificação de saúde chamando MapHealthChecks em Startup.Configure .

No aplicativo de exemplo, o ponto de extremidade de verificação de saúde é criado em /health ( BasicStartup.cs ):

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHealthChecks("/health");
        });
    }
}

Para executar o cenário de configuração básica usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario basic

Exemplo do Docker

O Docker oferece uma diretiva HEALTHCHECK interna que pode ser usada para verificar o status de um aplicativo que usa a configuração básica de verificação de integridade:

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

Criar verificações de integridade

As verificações de integridade são criadas pela implementação da interface IHealthCheck. O método CheckHealthAsync retorna um HealthCheckResult que indica a integridade como Healthy, Degraded ou Unhealthy. O resultado é gravado como uma resposta de texto sem formatação com um código de status configurável (a configuração é descrita na seção Opções de verificação de integridade). HealthCheckResult também pode retornar pares chave-valor opcionais.

A classe ExampleHealthCheck a seguir demonstra o layout de uma verificação de saúde. A lógica de verificações de saúde é colocada no CheckHealthAsync método . O exemplo a seguir define uma variável fi fitiva, healthCheckResultHealthy , como true . Se o valor de healthCheckResultHealthy for definido como , o status será false HealthCheckResult.Unhealthy retornado.

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("An unhealthy result."));
    }
}

Registrar os serviços de verificação de integridade

O ExampleHealthCheck tipo é adicionado aos serviços de verificação de saúde com em AddCheck Startup.ConfigureServices :

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

A sobrecarga AddCheck mostrada no exemplo a seguir define o status de falha (HealthStatus) como relatório quando a verificação de integridade relata uma falha. Se o status de falha for definido como null (padrão), HealthStatus.Unhealthy será relatado. Essa sobrecarga é um cenário útil para autores de biblioteca, em que o status de falha indicado pela biblioteca é imposto pelo aplicativo quando uma falha de verificação de integridade ocorre se a implementação da verificação de integridade respeita a configuração.

Marcas podem ser usadas para filtrar as verificações de integridade (descritas posteriormente na seção Filtrar verificações de integridade).

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck também pode executar uma função lambda. No seguinte exemplo, o nome da verificação de integridade é especificado como Example e a verificação sempre retorna um estado íntegro:

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

Chame AddTypeActivatedCheck para passar argumentos para uma implementação de verificação de saúde. No exemplo a seguir, aceita um inteiro e uma cadeia de TestHealthCheckWithArgs caracteres para uso quando CheckHealthAsync é chamado:

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        ...
    }
}

TestHealthCheckWithArgs é registrado chamando com AddTypeActivatedCheck o inteiro e a cadeia de caracteres passados para a implementação:

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

Usar roteamento de verificações de saúde

No Startup.Configure , chame no construtor de ponto de extremidade com a URL do ponto de extremidade ou o caminho MapHealthChecks relativo:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

Exigir host

Chame RequireHost para especificar um ou mais hosts permitidos para o ponto de extremidade de verificação de saúde. Os hosts devem ser Unicode em vez de punycode e podem incluir uma porta. Se uma coleção não for fornecida, qualquer host será aceito.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

Para obter mais informações, confira a seção Filtrar por porta.

Exigir autorização

Chame RequireAuthorization para executar o Middleware de Autorização no ponto de extremidade da solicitação de verificação de saúde. Uma RequireAuthorization sobrecarga aceita uma ou mais políticas de autorização. Se uma política não for fornecida, a política de autorização padrão será usada.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

Habilitar o CORS (Solicitações Entre Origens)

Embora a execução manual de verificações de saúde de um navegador não seja um cenário de uso comum, o Middleware cors pode ser habilitado chamando pontos de extremidade de RequireCors verificações de saúde. Uma RequireCors sobrecarga aceita um delegado do construtor de políticas cors ( ) ou um nome de CorsPolicyBuilder política. Se uma política não for fornecida, a política cors padrão será usada. Para obter mais informações, consulte Habilitar as solicitações entre origens (CORS) no ASP.NET Core.

Opções de verificação de integridade

HealthCheckOptions oferece uma oportunidade de personalizar o comportamento de verificação de integridade:

Filtrar verificações de integridade

Por padrão, o Middleware de Verificações de Saúde executa todas as verificações de saúde registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que retorne um booliano para a opção Predicate. No seguinte exemplo, a verificação de integridade Bar é filtrada por sua marca (bar_tag) na instrução condicional da função, em que true só é retornado se a propriedade Tags da verificação de integridade corresponde a foo_tag ou baz_tag:

Em Startup.ConfigureServices:

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

No Startup.Configure , o filtra a verificação de saúde Predicate "Barra". Somente Foo e Foo executem::

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

Personalizar o código de status HTTP

Use ResultStatusCodes para personalizar o mapeamento de status da integridade para códigos de status HTTP. As atribuições StatusCodes a seguir são os valores padrão usados pelo middleware. Altere os valores do código de status de acordo com suas necessidades.

Em Startup.Configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

Suprimir os cabeçalhos de cache

AllowCachingResponses controla se o Middleware de Verificações de Saúde adiciona cabeçalhos HTTP a uma resposta de investigação para evitar o cache de resposta. Se o valor é false (padrão), o middleware define ou substitui os cabeçalhos Cache-Control, Expires e Pragma para prevenir o cache de resposta. Se o valor é true, o middleware não modifica os cabeçalhos de cache da resposta.

Em Startup.Configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = false
    });
});

Personalizar a saída

Em Startup.Configure , de definido a opção como um delegado para escrever a HealthCheckOptions.ResponseWriter resposta:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

O delegado padrão grava uma resposta de texto sem formatação mínima com o valor de cadeia de caracteres de HealthReport.Status . Os delegados personalizados a seguir saídam uma resposta JSON personalizada.

O primeiro exemplo do aplicativo de exemplo demonstra como usar System.Text.Json :

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ?? 
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

O segundo exemplo demonstra como usarNewtonsoft.Js em:

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

No aplicativo de exemplo, comente a SYSTEM_TEXT_JSON diretiva de pré-processador em CustomWriterStartup.cs para habilitar Newtonsoft.Json a versão do WriteResponse .

A API de verificações de saúde não fornece suporte integrado para formatos de retorno JSON complexos porque o formato é específico para sua escolha de sistema de monitoramento. Personalize a resposta nos exemplos anteriores conforme necessário. Para obter mais informações sobre a serialização JSON com , consulte Como serializar e System.Text.Json serializar JSON no .NET.

Investigação de banco de dados

Uma verificação de integridade pode especificar uma consulta de banco de dados a ser executada como um teste booliano para indicar se o banco de dados está respondendo normalmente.

O aplicativo de exemplo usa , uma biblioteca de verificação de ASP.NET Core aplicativos, para executar uma verificação de SQL Server AspNetCore.Diagnostics.HealthChecks dados. O AspNetCore.Diagnostics.HealthChecks executa uma consulta SELECT 1 no banco de dados para confirmar se a conexão ao banco de dados está íntegra.

Aviso

Ao verificar uma conexão de banco de dados com uma consulta, escolha uma consulta que retorne rapidamente. A abordagem de consulta corre o risco de sobrecarregar o banco de dados e prejudicar o desempenho. Na maioria dos casos, a execução de uma consulta de teste não é necessária. É suficiente apenas estabelecer uma conexão bem-sucedida ao banco de dados. Se você achar necessário executar uma consulta, escolha uma consulta SELECT simples, como SELECT 1.

Inclua uma referência de pacote a AspNetCore.HealthChecks.SqlServer .

Fornecer uma cadeia de conexão de banco de dados válida appsettings.json no arquivo do aplicativo de exemplo. O aplicativo usa um banco de dados do SQL Server chamado HealthCheckSample:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. O aplicativo de exemplo chama o método com a cadeia de conexão do banco de AddSqlServer dados ( DbHealthStartup.cs ):

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

Um ponto de extremidade de verificação de saúde é criado chamando MapHealthChecks em Startup.Configure :

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

Para executar o cenário de investigação de banco de dados usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario db

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Investigação de DbContext do Entity Framework Core

A verificação DbContext confirma se o aplicativo pode se comunicar com o banco de dados configurado para um DbContext do EF Core. A verificação DbContext é compatível em aplicativos que:

AddDbContextCheck<TContext> registra uma verificação de integridade para um DbContext. O DbContext é fornecido como o TContext para o método. Uma sobrecarga está disponível para configurar o status de falha, marcas e uma consulta de teste personalizada.

Por padrão:

  • o DbContextHealthCheck chama o método CanConnectAsync do EF Core. Você pode personalizar qual operação é executada durante a verificação de integridade usando sobrecargas do método AddDbContextCheck.
  • O nome da verificação de integridade é o nome do tipo TContext.

No aplicativo de exemplo, AppDbContext é fornecido para e registrado como um serviço no ( AddDbContextCheck Startup.ConfigureServices DbContextHealthStartup.cs ):

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

Um ponto de extremidade de verificação de saúde é criado chamando MapHealthChecks em Startup.Configure :

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

Para executar o cenário de investigação DbContext usando o aplicativo de exemplo, confirme se o banco de dados especificado pela cadeia de conexão não existe na instância do SQL Server. Se o banco de dados existir, exclua-o.

Execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario dbcontext

Depois que o aplicativo estiver em execução, verifique o status da integridade fazendo uma solicitação para o ponto de extremidade /health em um navegador. O banco de dados e AppDbContext não existem e, portanto, o aplicativo fornece a seguinte resposta:

Unhealthy

Dispare o aplicativo de exemplo para criar o banco de dados. Faça uma solicitação para /createdatabase. O aplicativo responde:

Creating the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O banco de dados e o contexto existem e, portanto, o aplicativo responde:

Healthy

Dispare o aplicativo de exemplo para excluir o banco de dados. Faça uma solicitação para /deletedatabase. O aplicativo responde:

Deleting the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O aplicativo fornece uma resposta não íntegra:

Unhealthy

Investigações de preparação e atividade separadas

Em alguns cenários de hospedagem, é usado um par de verificações de integridade que distingue dois estados de aplicativo:

  • A preparação indica se o aplicativo está em execução normalmente, mas não está pronto para receber solicitações.
  • A liveness indica se um aplicativo teve uma queda e deve ser reiniciado.

Considere o exemplo a seguir: um aplicativo deve baixar um arquivo de configuração grande antes de estar pronto para processar solicitações. Não queremos que o aplicativo seja reiniciado se o download inicial falhar porque o aplicativo pode tentar baixar novamente o arquivo várias vezes. Usamos uma investigação de liveness para descrever a vida do processo, nenhuma verificação adicional é executada. Também queremos impedir que as solicitações seja enviadas ao aplicativo antes que o download do arquivo de configuração seja bem-sucedido. Usamos uma investigação de preparação para indicar um estado "não pronto" até que o download seja bem-sucedido e o aplicativo esteja pronto para receber solicitações.

O aplicativo de exemplo contém uma verificação de integridade para relatar a conclusão da tarefa de inicialização de execução longa em um Serviço Hospedado. O expõe uma propriedade, , que o serviço hospedado pode definir como quando sua tarefa de execução StartupHostedServiceHealthCheck longa é concluída ( StartupTaskCompleted true StartupHostedServiceHealthCheck.cs ):

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

A tarefa em segundo plano de execução longa é iniciada por um Serviço Hospedado ( Services/StartupHostedService ). Após a conclusão da tarefa, StartupHostedServiceHealthCheck.StartupTaskCompleted é definido como true:

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger, 
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

A verificação de integridade é registrada em AddCheck no Startup.ConfigureServices juntamente com o serviço hospedado. Como o serviço hospedado deve definir a propriedade na verificação de saúde, a verificação de saúde também é registrada no contêiner de serviço ( LivenessProbeStartup.cs ):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

Um ponto de extremidade de verificação de saúde é criado chamando MapHealthChecks em Startup.Configure . No aplicativo de exemplo, os pontos de extremidade de verificação de saúde são criados em:

  • /health/ready para a verificação de preparação. A verificação de preparação filtra as verificações de integridade para a verificação de integridade com a marca ready.
  • /health/live para a verificação de liveness. A verificação de vida filtra o StartupHostedServiceHealthCheck retornando no (para obter false mais HealthCheckOptions.Predicate informações, consulte Filtrar verificações de saúde)

No código de exemplo a seguir:

  • A verificação de preparação usa todas as verificações registradas com a marca 'ready'.
  • O Predicate exclui todas as verificações e retorna um 200-OK.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

Para executar o cenário de configuração de preparação/atividade usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario liveness

Em um navegador, visite /health/ready várias vezes até terem decorrido 15 segundos. A verificação de integridade relata Unhealthy para os primeiros 15 segundos. Após 15 segundos, o ponto de extremidade relata Healthy, que reflete a conclusão da tarefa de execução longa pelo serviço hospedado.

Este exemplo também cria um Publicador de Verificação de Integridade (implementação IHealthCheckPublisher) que executa a primeira verificação de preparação com um atraso de dois segundos. Para saber mais, confira a seção Publicador de Verificação de Integridade.

Exemplo do Kubernetes

O uso de verificações de preparação e atividade separadas é útil em um ambiente como o Kubernetes. No Kubernetes, um aplicativo pode precisar executar um trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade do banco de dados subjacente. O uso de verificações separadas permite que o orquestrador distinga se o aplicativo está funcionando, mas ainda não está pronto, ou se o aplicativo falhou ao ser iniciado. Para obter mais informações sobre as investigações de preparação e atividade no Kubernetes, confira Configurar investigações de preparação e atividade na documentação do Kubernetes.

O seguinte exemplo demonstra uma configuração de investigação de preparação do Kubernetes:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

Investigação baseada em métrica com um gravador de resposta personalizada

O aplicativo de exemplo demonstra uma verificação de integridade da memória com um gravador de resposta personalizada.

MemoryHealthCheck relata um estado degradado se o aplicativo usa mais de determinado limite de memória (1 GB no aplicativo de exemplo). O HealthCheckResult inclui informações do GC (Coletor de Lixo) para o aplicativo ( MemoryHealthCheck.cs ):

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ? 
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Em vez de permitir a verificação de integridade passando-a para AddCheck, a MemoryHealthCheck é registrada como um serviço. Todos os serviços registrados da IHealthCheck estão disponíveis para os serviços de verificação de integridade e middleware. Recomendamos registrar os serviços de verificação de integridade como serviços Singleton.

No CustomWriterStartup.cs do aplicativo de exemplo:

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

Um ponto de extremidade de verificação de saúde é criado chamando MapHealthChecks em Startup.Configure . Um delegado é fornecido à propriedade <Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions.ResponseWriter> para a saída de uma resposta JSON personalizada quando a verificação de saúde é WriteResponse executada:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

O WriteResponse delegado formatará o CompositeHealthCheckResult em um objeto JSON e produzirá a saída JSON para a resposta de verificação de saúde. Para obter mais informações, consulte a seção Personalizar saída.

Para executar a investigação baseada em métrica com a saída do gravador de resposta personalizada usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario writer

Observação

AspNetCore.Diagnostics.HealthChecks inclui cenários de verificação de saúde baseados em métrica, incluindo o armazenamento em disco e verificações de desempenho de valor máximo.

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Filtrar por porta

Chame com um padrão de URL que especifica uma porta para restringir solicitações de verificação RequireHost de saúde à porta MapHealthChecks especificada. Isso normalmente é usado em um ambiente de contêiner para expor uma porta para os serviços de monitoramento.

O aplicativo de exemplo configura a porta usando o Provedor de Configuração de Variáveis de Ambiente. A porta é definida no arquivo launchSettings.json e passada para o provedor de configuração por meio de uma variável de ambiente. Você também precisa configurar o servidor para escutar as solicitações na porta de gerenciamento.

Para usar o aplicativo de exemplo para demonstrar a configuração da porta de gerenciamento, crie launchSettings.json o arquivo em uma Properties pasta.

O seguinte arquivo no aplicativo de exemplo não está incluído nos arquivos de projeto do aplicativo de exemplo e Properties/launchSettings.json deve ser criado manualmente:

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Crie um ponto de extremidade de verificação de saúde chamando MapHealthChecks em Startup.Configure .

No aplicativo de exemplo, uma chamada para no ponto de extremidade em especifica a RequireHost porta de gerenciamento da Startup.Configure configuração:

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

Os pontos de extremidade são criados no aplicativo de exemplo no Startup.Configure . No código de exemplo a seguir:

  • A verificação de preparação usa todas as verificações registradas com a marca 'ready'.
  • O Predicate exclui todas as verificações e retorna um 200-OK.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

Observação

Você pode evitar a criação do arquivo no aplicativo de exemplo definindo a porta launchSettings.json de gerenciamento explicitamente no código. No local em que o é criado, adicione uma chamada para e forneça o ponto de extremidade da Program.cs porta de gerenciamento do HostBuilder ListenAnyIP aplicativo. No Configure de ManagementPortStartup.cs , especifique a porta de gerenciamento com RequireHost :

Program.cs:

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

Para executar o cenário de configuração de porta de gerenciamento usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario port

Distribuir uma biblioteca de verificação de integridade

Para distribuir uma verificação de integridade como uma biblioteca:

  1. Escreva uma verificação de integridade que implementa a interface IHealthCheck como uma classe autônoma. A classe pode depender da DI (injeção de dependência), da ativação de tipo e das opções nomeadas para acessar os dados de configuração.

    Na lógica de verificações de saúde de CheckHealthAsync :

    • data1 e data2 são usados no método para executar a lógica de verificação de saúde da investigação.
    • AccessViolationException é tratado.

    Quando um ocorre, o é retornado com o para permitir que os usuários configurem o status de falha AccessViolationException FailureStatus das HealthCheckResult verificações de saúde.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. Escreva um método de extensão com parâmetros que o aplicativo de consumo chama em seu método Startup.Configure. No seguinte exemplo, suponha a seguinte assinatura de método de verificação de integridade:

    ExampleHealthCheck(string, string, int )
    

    A assinatura anterior indica que a ExampleHealthCheck exige dados adicionais para processar a lógica de investigação de verificação de integridade. Os dados são fornecidos para o representante usado para criar a instância de verificação de integridade quando a verificação de integridade é registrada em um método de extensão. No seguinte exemplo, o chamador especifica itens opcionais:

    • nome da verificação de integridade (name). Se null, example_health_check é usado.
    • ponto de dados de cadeia de caracteres para a verificação de integridade (data1).
    • ponto de dados de inteiro para a verificação de integridade (data2). Se null, 1 é usado.
    • status de falha (HealthStatus). O padrão é null. Se null , será relatado para um status de HealthStatus.Unhealthy falha.
    • marcas (IEnumerable<string>).
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

Publicador de Verificação de Integridade

Quando um IHealthCheckPublisher é adicionado ao contêiner de serviços, o sistema de verificação de integridade periodicamente executa sua verificação de integridade e chama PublishAsync com o resultado. Isso é útil em um cenário de sistema de monitoramento de integridade baseada em push que espera que cada processo chame o sistema de monitoramento periodicamente para determinar a integridade.

A interface IHealthCheckPublisher tem um único método:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions permite que você defina:

  • Delay: o atraso inicial aplicado depois que o aplicativo é iniciado antes de executar IHealthCheckPublisher instâncias. O atraso é aplicado uma vez na inicialização e não ocorre em iterações subsequentes. O valor padrão é cinco segundos.
  • Period: o período de IHealthCheckPublisher execução. O valor padrão é 30 segundos.
  • Predicate: se Predicate for null (padrão), o serviço publicador de verificação de saúde executa todas as verificações de saúde registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que filtre o conjunto de verificações. O predicado é avaliado a cada período.
  • Timeout: o tempo de execução das verificações de saúde para todas IHealthCheckPublisher as instâncias. Use InfiniteTimeSpan para executar sem um tempo limite. O valor padrão é 30 segundos.

No aplicativo de exemplo, ReadinessPublisher é uma implementação IHealthCheckPublisher. O status da verificação de saúde é registrado para cada verificação em um nível de log de:

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks 
    // Middleware already logs health checks results. A real-world readiness 
    // check in a production app might perform a set of more expensive or 
    // time-consuming checks to determine if other resources are responding 
    // properly.
    public Task PublishAsync(HealthReport report, 
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

No exemplo LivenessProbeStartup do aplicativo de amostra, a verificação de preparação StartupHostedService tem um atraso de inicialização de dois segundos, e executa a verificação a cada 30 segundos. Para ativar a implementação IHealthCheckPublisher, o exemplo registra ReadinessPublisher como um serviço singleton no contêiner DI (injeção de dependência):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

Observação

AspNetCore.Diagnostics.HealthChecksinclui publicações para vários sistemas, incluindo o Application Insights.

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Restringir verificações de integridade com MapWhen

Use MapWhen para ramificar condicionalmente o pipeline de solicitação para pontos de extremidade de verificação de integridade.

No exemplo a seguir, ramifica o pipeline de solicitação para ativar o Middleware de Verificações de Integridade se uma MapWhen solicitação GET for recebida para o api/HealthCheck ponto de extremidade:

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

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

Para obter mais informações, consulte Middleware do ASP.NET Core.

ASP.NET Core oferece middleware de verificações de saúde e bibliotecas para relatar a saúde dos componentes de infraestrutura de aplicativo.

As verificações de integridade são expostas por um aplicativo como pontos de extremidade HTTP. Os pontos de extremidade de verificação de integridade podem ser configurados para uma variedade de cenários de monitoramento em tempo real:

  • As investigações de integridade podem ser usadas por orquestradores de contêineres e balanceadores de carga para verificar o status de um aplicativo. Por exemplo, um orquestrador de contêineres pode responder a uma verificação de integridade com falha interrompendo uma implantação sem interrupção ou reiniciando um contêiner. Um balanceador de carga pode reagir a um aplicativo não íntegro encaminhando o tráfego para fora da instância com falha para uma instância íntegra.
  • O uso de memória, disco e outros recursos de servidor físico pode ser monitorado quanto ao status de integridade.
  • As verificações de integridade podem testar as dependências do aplicativo, como bancos de dados e pontos de extremidade de serviço externo, para confirmar a disponibilidade e o funcionamento normal.

Exibir ou baixar código de exemplo (como baixar)

O aplicativo de exemplo inclui exemplos dos cenários descritos neste tópico. Para executar o aplicativo de exemplo para determinado cenário, use o comando dotnet run na pasta do projeto em um shell de comando. Confira o arquivo README.md do aplicativo de exemplo e as descrições de cenários neste tópico para obter detalhes sobre como usar o aplicativo de exemplo.

Pré-requisitos

As verificações de integridade são normalmente usadas com um orquestrador de contêineres ou um serviço de monitoramento externo para verificar o status de um aplicativo. Antes de adicionar verificações de integridade a um aplicativo, decida qual sistema de monitoramento será usado. O sistema de monitoramento determina quais tipos de verificações de integridade serão criados e como configurar seus pontos de extremidade.

Referenciar Microsoft.AspNetCore.App o metapacote ou adicionar uma referência de pacote ao Microsoft.AspNetCore.Diagnostics.HealthChecks pacote.

O aplicativo de exemplo fornece um código de inicialização para demonstrar verificações de integridade para vários cenários. O cenário de investigação de banco de dados verifica a saúde de uma conexão de banco de dados usando AspNetCore.Diagnostics.HealthChecks . O cenário investigação de DbContext verifica um banco de dados usando um DbContext do EF Core. Para explorar os cenários de banco de dados, o aplicativo de exemplo:

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Outro cenário de verificação de integridade demonstra como filtrar verificações de integridade para uma porta de gerenciamento. O aplicativo de exemplo exige a criação de um arquivo Properties/launchSettings.json que inclui a URL de gerenciamento e a porta de gerenciamento. Para obter mais informações, confira a seção Filtrar por porta.

Investigação de integridade básica

Para muitos aplicativos, uma configuração básica de investigação de integridade que relata a disponibilidade do aplicativo para processar solicitações (atividade) é suficiente para descobrir o status do aplicativo.

A configuração básica registra os serviços de verificação de saúde e chama o Middleware de Verificações de Saúde para responder em um ponto de extremidade de URL com uma resposta de saúde. Por padrão, nenhuma verificação de integridade específica é registrada para testar qualquer dependência ou subsistema específico. O aplicativo é considerado íntegro se consegue responder na URL do ponto de extremidade de integridade. O autor de resposta padrão grava o status ( ) como uma resposta de texto não criptografado de volta para o cliente, indicando um HealthStatus HealthStatus.Healthy status , ou HealthStatus.Degraded HealthStatus.Unhealthy .

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Adicione um ponto de extremidade para Middleware de Verificações de Integridade com UseHealthChecks no pipeline de processamento de solicitação do Startup.Configure .

No aplicativo de exemplo, o ponto de extremidade de verificação de integridade é criado em /health (BasicStartup.cs):

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseHealthChecks("/health");
    }
}

Para executar o cenário de configuração básica usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario basic

Exemplo do Docker

O Docker oferece uma diretiva HEALTHCHECK interna que pode ser usada para verificar o status de um aplicativo que usa a configuração básica de verificação de integridade:

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

Criar verificações de integridade

As verificações de integridade são criadas pela implementação da interface IHealthCheck. O método CheckHealthAsync retorna um HealthCheckResult que indica a integridade como Healthy, Degraded ou Unhealthy. O resultado é gravado como uma resposta de texto sem formatação com um código de status configurável (a configuração é descrita na seção Opções de verificação de integridade). HealthCheckResult também pode retornar pares chave-valor opcionais.

Verificação de integridade de exemplo

A classe ExampleHealthCheck a seguir demonstra o layout de uma verificação de saúde. A lógica de verificações de saúde é colocada no CheckHealthAsync método . O exemplo a seguir define uma variável fi fitiva, healthCheckResultHealthy , como true . Se o valor de healthCheckResultHealthy for definido como , o status será false HealthCheckResult.Unhealthy retornado.

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The check indicates a healthy result."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The check indicates an unhealthy result."));
    }
}

Registrar os serviços de verificação de integridade

O ExampleHealthCheck tipo é adicionado aos serviços de verificação de saúde no com Startup.ConfigureServices AddCheck :

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

A sobrecarga AddCheck mostrada no exemplo a seguir define o status de falha (HealthStatus) como relatório quando a verificação de integridade relata uma falha. Se o status de falha for definido como null (padrão), HealthStatus.Unhealthy será relatado. Essa sobrecarga é um cenário útil para autores de biblioteca, em que o status de falha indicado pela biblioteca é imposto pelo aplicativo quando uma falha de verificação de integridade ocorre se a implementação da verificação de integridade respeita a configuração.

Marcas podem ser usadas para filtrar as verificações de integridade (descritas posteriormente na seção Filtrar verificações de integridade).

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck também pode executar uma função lambda. No exemplo a Startup.ConfigureServices seguir, o nome da verificação de saúde é especificado como Example e a verificação sempre retorna um estado ntente:

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

Usar o Middleware de Verificações de Integridade

Em Startup.Configure, chame UseHealthChecks do pipeline de processamento com a URL de ponto de extremidade ou o caminho relativo:

app.UseHealthChecks("/health");

Se as verificações de integridade precisarem escutar uma porta específica, use uma sobrecarga igual a UseHealthChecks para definir a porta (descrito posteriormente na seção Filtrar por porta):

app.UseHealthChecks("/health", port: 8000);

Opções de verificação de integridade

HealthCheckOptions oferece uma oportunidade de personalizar o comportamento de verificação de integridade:

Filtrar verificações de integridade

Por padrão, o Middleware de Verificações de Saúde executa todas as verificações de saúde registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que retorne um booliano para a opção Predicate. No seguinte exemplo, a verificação de integridade Bar é filtrada por sua marca (bar_tag) na instrução condicional da função, em que true só é retornado se a propriedade Tags da verificação de integridade corresponde a foo_tag ou baz_tag:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
        .AddCheck("Foo", () =>
            HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
        .AddCheck("Bar", () =>
            HealthCheckResult.Unhealthy("Bar is unhealthy!"), 
                tags: new[] { "bar_tag" })
        .AddCheck("Baz", () =>
            HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });
}

public void Configure(IApplicationBuilder app)
{
    app.UseHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
}

Personalizar o código de status HTTP

Use ResultStatusCodes para personalizar o mapeamento de status da integridade para códigos de status HTTP. As atribuições StatusCodes a seguir são os valores padrão usados pelo middleware. Altere os valores do código de status de acordo com suas necessidades.

Em Startup.Configure:

//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
    ResultStatusCodes =
    {
        [HealthStatus.Healthy] = StatusCodes.Status200OK,
        [HealthStatus.Degraded] = StatusCodes.Status200OK,
        [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
});

Suprimir os cabeçalhos de cache

AllowCachingResponses controla se o Middleware de Verificações de Saúde adiciona cabeçalhos HTTP a uma resposta de investigação para evitar o cache de resposta. Se o valor é false (padrão), o middleware define ou substitui os cabeçalhos Cache-Control, Expires e Pragma para prevenir o cache de resposta. Se o valor é true, o middleware não modifica os cabeçalhos de cache da resposta.

Em Startup.Configure:

//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
    AllowCachingResponses = false
});

Personalizar a saída

A opção ResponseWriter obtém ou define um representante usado para gravar a resposta. O delegado padrão grava uma resposta de texto sem formatação mínima com o valor de cadeia de caracteres de HealthReport.Status .

Em Startup.Configure:

// using Microsoft.AspNetCore.Diagnostics.HealthChecks;
// using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
    ResponseWriter = WriteResponse
});

O delegado padrão grava uma resposta de texto sem formatação mínima com o valor de cadeia de caracteres de HealthReport.Status . O delegado personalizado a seguir, WriteResponse , saída de uma resposta JSON personalizada:

private static Task WriteResponse(HttpContext httpContext, HealthReport result)
{
    httpContext.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));
    return httpContext.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

O sistema de verificações de saúde não fornece suporte integrado para formatos de retorno JSON complexos porque o formato é específico à sua escolha de sistema de monitoramento. Sinta-se à vontade JObject para personalizar o no exemplo anterior conforme necessário para atender às suas necessidades.

Investigação de banco de dados

Uma verificação de integridade pode especificar uma consulta de banco de dados a ser executada como um teste booliano para indicar se o banco de dados está respondendo normalmente.

O aplicativo de exemplo usa , uma biblioteca de verificação de ASP.NET Core aplicativos, para executar uma verificação de SQL Server AspNetCore.Diagnostics.HealthChecks dados. O AspNetCore.Diagnostics.HealthChecks executa uma consulta SELECT 1 no banco de dados para confirmar se a conexão ao banco de dados está íntegra.

Aviso

Ao verificar uma conexão de banco de dados com uma consulta, escolha uma consulta que retorne rapidamente. A abordagem de consulta corre o risco de sobrecarregar o banco de dados e prejudicar o desempenho. Na maioria dos casos, a execução de uma consulta de teste não é necessária. É suficiente apenas estabelecer uma conexão bem-sucedida ao banco de dados. Se você achar necessário executar uma consulta, escolha uma consulta SELECT simples, como SELECT 1.

Inclua uma referência de pacote a AspNetCore.HealthChecks.SqlServer .

Fornecer uma cadeia de conexão de banco de dados válida appsettings.json no arquivo do aplicativo de exemplo. O aplicativo usa um banco de dados do SQL Server chamado HealthCheckSample:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Debug"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. O aplicativo de exemplo chama o método AddSqlServer com a cadeia de conexão do banco de dados (DbHealthStartup.cs):

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
        .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
}

Chame o Middleware de Verificações de Integridade no pipeline de processamento de aplicativos no Startup.Configure :

app.UseHealthChecks("/health");

Para executar o cenário de investigação de banco de dados usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario db

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido nem suportado pela Microsoft.

Investigação de DbContext do Entity Framework Core

A verificação DbContext confirma se o aplicativo pode se comunicar com o banco de dados configurado para um DbContext do EF Core. A verificação DbContext é compatível em aplicativos que:

AddDbContextCheck<TContext> registra uma verificação de integridade para um DbContext. O DbContext é fornecido como o TContext para o método. Uma sobrecarga está disponível para configurar o status de falha, marcas e uma consulta de teste personalizada.

Por padrão:

  • o DbContextHealthCheck chama o método CanConnectAsync do EF Core. Você pode personalizar qual operação é executada durante a verificação de integridade usando sobrecargas do método AddDbContextCheck.
  • O nome da verificação de integridade é o nome do tipo TContext.

No aplicativo de exemplo, é fornecido e registrado como um serviço AppDbContext AddDbContextCheck em ( Startup.ConfigureServices DbContextHealthStartup.cs):

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
        .AddDbContextCheck<AppDbContext>();

    services.AddDbContext<AppDbContext>(options =>
    {
        options.UseSqlServer(
            Configuration["ConnectionStrings:DefaultConnection"]);
    });
}

No aplicativo de exemplo, UseHealthChecks adiciona o Middleware de Verificações de Saúde no Startup.Configure .

app.UseHealthChecks("/health");

Para executar o cenário de investigação DbContext usando o aplicativo de exemplo, confirme se o banco de dados especificado pela cadeia de conexão não existe na instância do SQL Server. Se o banco de dados existir, exclua-o.

Execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario dbcontext

Depois que o aplicativo estiver em execução, verifique o status da integridade fazendo uma solicitação para o ponto de extremidade /health em um navegador. O banco de dados e AppDbContext não existem e, portanto, o aplicativo fornece a seguinte resposta:

Unhealthy

Dispare o aplicativo de exemplo para criar o banco de dados. Faça uma solicitação para /createdatabase. O aplicativo responde:

Creating the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O banco de dados e o contexto existem e, portanto, o aplicativo responde:

Healthy

Dispare o aplicativo de exemplo para excluir o banco de dados. Faça uma solicitação para /deletedatabase. O aplicativo responde:

Deleting the database...
Done!
Navigate to /health to see the health status.

Faça uma solicitação ao ponto de extremidade /health. O aplicativo fornece uma resposta não íntegra:

Unhealthy

Investigações de preparação e atividade separadas

Em alguns cenários de hospedagem, é usado um par de verificações de integridade que distingue dois estados de aplicativo:

  • A preparação indica se o aplicativo está em execução normalmente, mas não está pronto para receber solicitações.
  • A liveness indica se um aplicativo teve uma queda e deve ser reiniciado.

Considere o exemplo a seguir: um aplicativo deve baixar um arquivo de configuração grande antes de estar pronto para processar solicitações. Não queremos que o aplicativo seja reiniciado se o download inicial falhar porque o aplicativo pode tentar baixar novamente o arquivo várias vezes. Usamos uma investigação de liveness para descrever a vida do processo, nenhuma verificação adicional é executada. Também queremos impedir que as solicitações seja enviadas ao aplicativo antes que o download do arquivo de configuração seja bem-sucedido. Usamos uma investigação de prontidão para indicar um estado "não pronto" até que o download seja bem sucedido e o aplicativo esteja pronto para receber solicitações.

O aplicativo de exemplo contém uma verificação de integridade para relatar a conclusão da tarefa de inicialização de execução longa em um Serviço Hospedado. A StartupHostedServiceHealthCheck expõe uma propriedade StartupTaskCompleted, que o serviço hospedado poderá definir como true quando sua tarefa de execução longa estiver concluída (StartupHostedServiceHealthCheck.cs):

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

A tarefa em segundo plano de execução longa é iniciada por um Serviço Hospedado (Services/StartupHostedService). Após a conclusão da tarefa, StartupHostedServiceHealthCheck.StartupTaskCompleted é definido como true:

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger, 
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

A verificação de integridade é registrada em AddCheck no Startup.ConfigureServices juntamente com o serviço hospedado. Como o serviço hospedado precisa definir a propriedade na verificação de integridade, a verificação de integridade também é registrada no contêiner de serviço (LivenessProbeStartup.cs):

public void ConfigureServices(IServiceCollection services)
{
    services.AddHostedService<StartupHostedService>();
    services.AddSingleton<StartupHostedServiceHealthCheck>();

    services.AddHealthChecks()
        .AddCheck<StartupHostedServiceHealthCheck>(
            "hosted_service_startup", 
            failureStatus: HealthStatus.Degraded, 
            tags: new[] { "ready" });

    services.Configure<HealthCheckPublisherOptions>(options =>
    {
        options.Delay = TimeSpan.FromSeconds(2);
        options.Predicate = (check) => check.Tags.Contains("ready");
    });

    // The following workaround permits adding an IHealthCheckPublisher 
    // instance to the service container when one or more other hosted 
    // services have already been added to the app. This workaround
    // won't be required with the release of ASP.NET Core 3.0. For more 
    // information, see: https://github.com/aspnet/Extensions/issues/639.
    services.TryAddEnumerable(
        ServiceDescriptor.Singleton(typeof(IHostedService), 
            typeof(HealthCheckPublisherOptions).Assembly
                .GetType(HealthCheckServiceAssembly)));

    services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}

Chame o middleware de verificações de integridade no pipeline de processamento de aplicativo no Startup.Configure . No aplicativo de exemplo, os pontos de extremidade de verificação de integridade são criados em /health/ready para a verificação de preparação e em /health/live para a verificação de atividade. A verificação de preparação filtra as verificações de integridade para a verificação de integridade com a marca ready. A verificação de vida filtra o StartupHostedServiceHealthCheck retornando false no HealthCheckOptions.Predicate (para obter mais informações, consulte Filtrar verificações de integridade):

app.UseHealthChecks("/health/ready", new HealthCheckOptions()
{
    Predicate = (check) => check.Tags.Contains("ready"), 
});

app.UseHealthChecks("/health/live", new HealthCheckOptions()
{
    Predicate = (_) => false
});

Para executar o cenário de configuração de preparação/atividade usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario liveness

Em um navegador, visite /health/ready várias vezes até terem decorrido 15 segundos. A verificação de integridade informa Não íntegro para os primeiros 15 segundos. Após 15 segundos, o ponto de extremidade informa Íntegro, que reflete a conclusão da tarefa de execução longa pelo serviço hospedado.

Este exemplo também cria um Publicador de Verificação de Integridade (implementação IHealthCheckPublisher) que executa a primeira verificação de preparação com um atraso de dois segundos. Para saber mais, confira a seção Publicador de Verificação de Integridade.

Exemplo do Kubernetes

O uso de verificações de preparação e atividade separadas é útil em um ambiente como o Kubernetes. No Kubernetes, um aplicativo pode precisar executar um trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade do banco de dados subjacente. O uso de verificações separadas permite que o orquestrador distinga se o aplicativo está funcionando, mas ainda não está pronto, ou se o aplicativo falhou ao ser iniciado. Para obter mais informações sobre as investigações de preparação e atividade no Kubernetes, confira Configurar investigações de preparação e atividade na documentação do Kubernetes.

O seguinte exemplo demonstra uma configuração de investigação de preparação do Kubernetes:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

Investigação baseada em métrica com um gravador de resposta personalizada

O aplicativo de exemplo demonstra uma verificação de integridade da memória com um gravador de resposta personalizada.

MemoryHealthCheck relata um status não íntegro se o aplicativo usar mais do que um determinado limite de memória (1 GB no aplicativo de exemplo). O HealthCheckResult inclui informações de GC (Coletor de Lixo) para o aplicativo (MemoryHealthCheck.cs):

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };

        var status = (allocated < options.Threshold) ? 
            HealthStatus.Healthy : HealthStatus.Unhealthy;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Em vez de permitir a verificação de integridade passando-a para AddCheck, a MemoryHealthCheck é registrada como um serviço. Todos os serviços registrados da IHealthCheck estão disponíveis para os serviços de verificação de integridade e middleware. Recomendamos registrar os serviços de verificação de integridade como serviços Singleton.

No aplicativo de exemplo (CustomWriterStartup. cs):

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
        .AddMemoryHealthCheck("memory");
}

Chame o middleware de verificações de integridade no pipeline de processamento de aplicativo no Startup.Configure . Um representante WriteResponse é fornecido para a propriedade ResponseWriter para gerar uma resposta JSON personalizada quando a verificação de integridade é executada:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseHealthChecks("/health", new HealthCheckOptions()
    {
        // This custom writer formats the detailed status as JSON.
        ResponseWriter = WriteResponse
    });
}

O método WriteResponse formata o CompositeHealthCheckResult em um objeto JSON e produz a saída JSON para a resposta da verificação de integridade:

private static Task WriteResponse(HttpContext httpContext, 
    HealthReport result)
{
    httpContext.Response.ContentType = "application/json; charset=utf-8";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));
    return httpContext.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

Para executar a investigação baseada em métrica com a saída do gravador de resposta personalizada usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario writer

Observação

AspNetCore.Diagnostics.HealthChecks inclui cenários de verificação de integridade baseados em métrica, incluindo armazenamento em disco e verificações de vida de valor máximo.

AspNetCore.Diagnostics.HealthChecks Não é mantido nem tem suporte da Microsoft.

Filtrar por porta

A chamada a UseHealthChecks com uma porta restringe as solicitações de verificação de integridade à porta especificada. Isso normalmente é usado em um ambiente de contêiner para expor uma porta para os serviços de monitoramento.

O aplicativo de exemplo configura a porta usando o Provedor de Configuração de Variáveis de Ambiente. A porta é definida no arquivo launchSettings.json e passada para o provedor de configuração por meio de uma variável de ambiente. Você também precisa configurar o servidor para escutar as solicitações na porta de gerenciamento.

Para usar o aplicativo de exemplo para demonstrar a configuração de porta de gerenciamento, crie o arquivo launchSettings.json em uma pasta Properties.

As seguintes Propriedades/launchSettings.jsno arquivo no aplicativo de exemplo não estão incluídas nos arquivos de projeto do aplicativo de exemplo e devem ser criadas manualmente:

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. A chamada a UseHealthChecks especifica a porta de gerenciamento (ManagementPortStartup.cs):

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseHealthChecks("/health", port: Configuration["ManagementPort"]);

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                "Navigate to " + 
                $"http://localhost:{Configuration["ManagementPort"]}/health " +
                "to see the health status.");
        });
    }
}

Observação

Evite a criação do arquivo launchSettings.json no aplicativo de exemplo definindo as URLs e a porta de gerenciamento explicitamente no código. Em Program.cs, em que o WebHostBuilder é criado, adicione uma chamada a UseUrls e forneça o ponto de extremidade da resposta normal do aplicativo e o ponto de extremidade da porta de gerenciamento. Em ManagementPortStartup.cs, em que UseHealthChecks é chamado, especifique a porta de gerenciamento explicitamente.

Program. cs:

return new WebHostBuilder()
    .UseConfiguration(config)
    .UseUrls("http://localhost:5000/;http://localhost:5001/")
    .ConfigureLogging(builder =>
    {
        builder.SetMinimumLevel(LogLevel.Trace);
        builder.AddConfiguration(config);
        builder.AddConsole();
    })
    .UseKestrel()
    .UseStartup(startupType)
    .Build();

ManagementPortStartup.cs:

app.UseHealthChecks("/health", port: 5001);

Para executar o cenário de configuração de porta de gerenciamento usando o aplicativo de exemplo, execute o seguinte comando na pasta do projeto em um shell de comando:

dotnet run --scenario port

Distribuir uma biblioteca de verificação de integridade

Para distribuir uma verificação de integridade como uma biblioteca:

  1. Escreva uma verificação de integridade que implementa a interface IHealthCheck como uma classe autônoma. A classe pode depender da DI (injeção de dependência), da ativação de tipo e das opções nomeadas para acessar os dados de configuração.

    Na lógica de verificações de integridade de CheckHealthAsync :

    • data1 e data2 são usados no método para executar a lógica de verificação de integridade da investigação.
    • AccessViolationException é manipulado.

    Quando ocorre um erro AccessViolationException , o FailureStatus é retornado com o HealthCheckResult para permitir que os usuários configurem o status de falha de verificações de integridade.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public class ExampleHealthCheck : IHealthCheck
    {
        private readonly string _data1;
        private readonly int? _data2;
    
        public ExampleHealthCheck(string data1, int? data2)
        {
            _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
            _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
        }
    
        public async Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context, CancellationToken cancellationToken)
        {
            try
            {
                return HealthCheckResult.Healthy();
            }
            catch (AccessViolationException ex)
            {
                return new HealthCheckResult(
                    context.Registration.FailureStatus,
                    description: "An access violation occurred during the check.",
                    exception: ex,
                    data: null);
            }
        }
    }
    
  2. Escreva um método de extensão com parâmetros que o aplicativo de consumo chama em seu método Startup.Configure. No seguinte exemplo, suponha a seguinte assinatura de método de verificação de integridade:

    ExampleHealthCheck(string, string, int )
    

    A assinatura anterior indica que a ExampleHealthCheck exige dados adicionais para processar a lógica de investigação de verificação de integridade. Os dados são fornecidos para o representante usado para criar a instância de verificação de integridade quando a verificação de integridade é registrada em um método de extensão. No seguinte exemplo, o chamador especifica itens opcionais:

    • nome da verificação de integridade (name). Se null, example_health_check é usado.
    • ponto de dados de cadeia de caracteres para a verificação de integridade (data1).
    • ponto de dados de inteiro para a verificação de integridade (data2). Se null, 1 é usado.
    • status de falha (HealthStatus). O padrão é null. Se null , HealthStatus.Unhealthy for relatado um status de falha.
    • marcas (IEnumerable<string>).
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

Publicador de Verificação de Integridade

Quando um IHealthCheckPublisher é adicionado ao contêiner de serviços, o sistema de verificação de integridade periodicamente executa sua verificação de integridade e chama PublishAsync com o resultado. Isso é útil em um cenário de sistema de monitoramento de integridade baseada em push que espera que cada processo chame o sistema de monitoramento periodicamente para determinar a integridade.

A interface IHealthCheckPublisher tem um único método:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions permite que você defina:

  • Delay: O atraso inicial aplicado depois que o aplicativo é iniciado antes de executar IHealthCheckPublisher instâncias. O atraso é aplicado uma vez na inicialização e não ocorre em iterações subsequentes. O valor padrão é cinco segundos.
  • Period: O período de IHealthCheckPublisher execução. O valor padrão é 30 segundos.
  • Predicate: Se Predicate for null (padrão), o serviço de Publicador de verificação de integridade executará todas as verificações de integridade registradas. Para executar um subconjunto das verificações de integridade, forneça uma função que filtre o conjunto de verificações. O predicado é avaliado a cada período.
  • Timeout: O tempo limite para executar as verificações de integridade de todas as IHealthCheckPublisher instâncias. Use InfiniteTimeSpan para executar sem um tempo limite. O valor padrão é 30 segundos.

Aviso

Na versão para ASP.NET Core 2.2, a configuração de Period não é respeitada pela implementação IHealthCheckPublisher; ela define o valor de Delay. esse problema foi resolvido no ASP.NET Core 3,0.

No aplicativo de exemplo, ReadinessPublisher é uma implementação IHealthCheckPublisher. O status da verificação de integridade é registrado para cada verificação:

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks 
    // Middleware already logs health checks results. A real-world readiness 
    // check in a production app might perform a set of more expensive or 
    // time-consuming checks to determine if other resources are responding 
    // properly.
    public Task PublishAsync(HealthReport report, 
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}", 
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

No exemplo LivenessProbeStartup do aplicativo de amostra, a verificação de preparação StartupHostedService tem um atraso de inicialização de dois segundos, e executa a verificação a cada 30 segundos. Para ativar a implementação IHealthCheckPublisher, o exemplo registra ReadinessPublisher como um serviço singleton no contêiner DI (injeção de dependência):

public void ConfigureServices(IServiceCollection services)
{
    services.AddHostedService<StartupHostedService>();
    services.AddSingleton<StartupHostedServiceHealthCheck>();

    services.AddHealthChecks()
        .AddCheck<StartupHostedServiceHealthCheck>(
            "hosted_service_startup", 
            failureStatus: HealthStatus.Degraded, 
            tags: new[] { "ready" });

    services.Configure<HealthCheckPublisherOptions>(options =>
    {
        options.Delay = TimeSpan.FromSeconds(2);
        options.Predicate = (check) => check.Tags.Contains("ready");
    });

    // The following workaround permits adding an IHealthCheckPublisher 
    // instance to the service container when one or more other hosted 
    // services have already been added to the app. This workaround
    // won't be required with the release of ASP.NET Core 3.0. For more 
    // information, see: https://github.com/aspnet/Extensions/issues/639.
    services.TryAddEnumerable(
        ServiceDescriptor.Singleton(typeof(IHostedService), 
            typeof(HealthCheckPublisherOptions).Assembly
                .GetType(HealthCheckServiceAssembly)));

    services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}

Observação

A solução alternativa a seguir permite a adição de uma instância IHealthCheckPublisher ao contêiner de serviço quando um ou mais serviços hospedados já tiverem sido adicionados ao aplicativo. essa solução alternativa não será necessária no ASP.NET Core 3,0.

private const string HealthCheckServiceAssembly =
    "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckPublisherHostedService";

services.TryAddEnumerable(
    ServiceDescriptor.Singleton(typeof(IHostedService),
        typeof(HealthCheckPublisherOptions).Assembly
            .GetType(HealthCheckServiceAssembly)));

Observação

AspNetCore.Diagnostics.HealthChecksinclui Publicadores para vários sistemas, incluindo Application insights.

AspNetCore.Diagnostics.HealthChecks Não é mantido nem tem suporte da Microsoft.

Restringir verificações de integridade com MapWhen

Use MapWhen para ramificar condicionalmente o pipeline de solicitação para pontos de extremidade de verificação de integridade.

No exemplo a seguir, MapWhen ramifica o pipeline de solicitação para ativar o middleware de verificações de integridade se uma solicitação get for recebida para o api/HealthCheck ponto de extremidade:

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

app.UseMvc();

Para obter mais informações, consulte Middleware do ASP.NET Core.