Verificações de integridade no ASP.NET Core

Por Glenn Condron

ASP.NET Core oferece middleware de verificações de integridade e bibliotecas para relatar a integridade dos componentes da infraestrutura do 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 vários 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.

Verificações de integridade normalmente são usadas com um serviço de monitoramento externo ou orquestrador de contêiner 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.

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 será considerado íntegro se puder responder na URL do ponto de extremidade de integridade. O gravador de resposta padrão grava HealthStatus como uma resposta sem texto simples para o cliente. O HealthStatus é HealthStatus.Healthy, HealthStatus.Degradedou HealthStatus.Unhealthy.

Registre os serviços de verificação de integridade com AddHealthChecks em Program.cs. Crie um ponto de extremidade de verificação de integridade chamando MapHealthChecks.

O exemplo a seguir cria um ponto de extremidade de verificação de integridade em /healthz:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

Docker HEALTHCHECK

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/healthz || exit

O exemplo anterior usa curl para fazer uma solicitação HTTP para o ponto de extremidade de verificação de integridade em /healthz. curl não está incluído nas imagens de contêiner do .NET Linux, mas pode ser adicionado instalando o pacote necessário no Dockerfile. Os contêineres que usam imagens com base no Linux Alpine podem usar os incluídos wget no lugar de curl.

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 sem 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.

O exemplo a seguir demonstra o layout de uma verificação de integridade:

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

        // ...

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

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

A lógica da verificação de integridade é colocada no CheckHealthAsync método. O exemplo anterior define uma variável fictícia como isHealthytrue. Se o valor for isHealthy definido como false, o HealthCheckRegistration.FailureStatus status será retornado.

Se CheckHealthAsync gerar uma exceção durante a verificação, uma nova HealthReportEntry será retornada com seu HealthReportEntry.Status conjunto para .FailureStatus Esse status é definido por AddCheck (consulte a seção Registrar serviços de verificação de integridade ) e inclui a exceção interna que causou a falha de verificação. O Description conjunto é definido como a mensagem da exceção.

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

Para registrar um serviço de verificação de integridade, chame AddCheckProgram.cs:

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>("Sample");

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 é definido como null (padrão), HealthStatus.Unhealthy é 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 verificações de integridade. As marcas são descritas na seção Filtrar verificações de integridade .

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" });

AddCheck também pode executar uma função lambda. No exemplo a seguir, a verificação de integridade sempre retorna um resultado íntegro:

builder.Services.AddHealthChecks()
    .AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));

Chamar AddTypeActivatedCheck para passar argumentos para uma implementação de verificação de integridade. No exemplo a seguir, uma verificação de integridade ativada por tipo aceita um inteiro e uma cadeia de caracteres em seu construtor:

public class SampleHealthCheckWithArgs : IHealthCheck
{
    private readonly int _arg1;
    private readonly string _arg2;

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);

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

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

Para registrar a verificação de integridade anterior, chame AddTypeActivatedCheck com o inteiro e a cadeia de caracteres passadas como argumentos:

builder.Services.AddHealthChecks()
    .AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" },
        args: new object[] { 1, "Arg" });

Usar o roteamento de verificações de integridade

In Program.cs, call MapHealthChecks on the endpoint builder with the endpoint URL or relative path:

app.MapHealthChecks("/healthz");

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.MapHealthChecks("/healthz")
    .RequireHost("www.contoso.com:5001");

Para restringir o ponto de extremidade de verificação de integridade a responder somente em uma porta específica, especifique uma porta na chamada para RequireHost. Essa abordagem normalmente é usada em um ambiente de contêiner para expor uma porta para serviços de monitoramento:

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001");

Para obter mais informações, consulte a correspondência de host em rotas com RequireHost.

Exigir autorização

Chame RequireAuthorization para executar o Middleware de Autorização no ponto de extremidade da 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.MapHealthChecks("/healthz")
    .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 comum, o MIDDLEware CORS pode ser habilitado chamando RequireCors os pontos de extremidade de verificação de integridade. A RequireCors sobrecarga aceita um delegado do construtor de políticas CORS (CorsPolicyBuilder) ou um nome de política. Para obter mais informações, consulte Habilitar SOLICITAções de Origem Cruzada (CORS) em 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.

O exemplo a seguir filtra as verificações de integridade para que somente aquelas marcadas com sample execução:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});

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 de código de status para atender aos seus requisitos:

app.MapHealthChecks("/healthz", 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 for true, o middleware não modificará os cabeçalhos de cache da resposta:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    AllowCachingResponses = false
});

Personalizar a saída

Para personalizar a saída de um relatório de verificações de integridade, defina a HealthCheckOptions.ResponseWriter propriedade como um delegado que grava a resposta:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResponseWriter = WriteResponse
});

O representante padrão grava uma resposta mínima de texto sem formatação com o valor de cadeia de caracteres HealthReport.Status. O delegado personalizado a seguir gera uma resposta ON personalizada JSusando System.Text.Json:

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

    var options = new JsonWriterOptions { Indented = true };

    using var memoryStream = new MemoryStream();
    using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
    {
        jsonWriter.WriteStartObject();
        jsonWriter.WriteString("status", healthReport.Status.ToString());
        jsonWriter.WriteStartObject("results");

        foreach (var healthReportEntry in healthReport.Entries)
        {
            jsonWriter.WriteStartObject(healthReportEntry.Key);
            jsonWriter.WriteString("status",
                healthReportEntry.Value.Status.ToString());
            jsonWriter.WriteString("description",
                healthReportEntry.Value.Description);
            jsonWriter.WriteStartObject("data");

            foreach (var item in healthReportEntry.Value.Data)
            {
                jsonWriter.WritePropertyName(item.Key);

                JsonSerializer.Serialize(jsonWriter, item.Value,
                    item.Value?.GetType() ?? typeof(object));
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WriteEndObject();
        }

        jsonWriter.WriteEndObject();
        jsonWriter.WriteEndObject();
    }

    return context.Response.WriteAsync(
        Encoding.UTF8.GetString(memoryStream.ToArray()));
}

A API de verificações de integridade não fornece suporte interno para formatos de retorno ON complexos JSporque 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 JSserialização ON 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.

AspNetCore.Diagnostics.HealthChecks, uma biblioteca de verificação de integridade para aplicativos ASP.NET Core, inclui uma verificação de integridade executada 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.

Para usar esse SQL Server verificação de integridade, inclua uma referência de pacote ao AspNetCore.HealthChecks.SqlServer pacote NuGet. O exemplo a seguir registra a verificação de integridade do SQL Server:

builder.Services.AddHealthChecks()
    .AddSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection"));

Observação

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

Investigação de DbContext do Entity Framework Core

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

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

Por padrão:

  • O DbContextHealthCheck método de chamadasEF Core.CanConnectAsync 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.

O exemplo a seguir registra um DbContext e um associado DbContextHealthCheck:

builder.Services.AddDbContext<SampleDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddHealthChecks()
    .AddDbContextCheck<SampleDbContext>();

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

Em alguns cenários de hospedagem, um par de verificações de integridade é usado para distinguir 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 dinâmica 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 porque o aplicativo pode tentar baixar novamente o arquivo várias vezes. Usamos uma investigação de dinâmica para descrever a dinâmica do processo, nenhuma outra verificação é executada. Também queremos impedir que as solicitações sejam enviadas ao aplicativo antes que o download do arquivo de configuração tenha êxito. 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.

A tarefa em segundo plano a seguir simula um processo de inicialização que leva aproximadamente 15 segundos. Depois de concluída, a tarefa define a StartupHealthCheck.StartupCompleted propriedade como verdadeira:

public class StartupBackgroundService : BackgroundService
{
    private readonly StartupHealthCheck _healthCheck;

    public StartupBackgroundService(StartupHealthCheck healthCheck)
        => _healthCheck = healthCheck;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Simulate the effect of a long-running task.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _healthCheck.StartupCompleted = true;
    }
}

O StartupHealthCheck relatório relata a conclusão da tarefa de inicialização de execução longa e expõe a StartupCompleted propriedade que é definida pelo serviço em segundo plano:

public class StartupHealthCheck : IHealthCheck
{
    private volatile bool _isReady;

    public bool StartupCompleted
    {
        get => _isReady;
        set => _isReady = value;
    }

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

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

A verificação de integridade é registrada em AddCheck no Program.cs 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 como um singleton:

builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();

builder.Services.AddHealthChecks()
    .AddCheck<StartupHealthCheck>(
        "Startup",
        tags: new[] { "ready" });

Para criar dois pontos de extremidade de verificação de integridade diferentes, chame MapHealthChecks duas vezes:

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});

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

O exemplo anterior cria os seguintes pontos de extremidade de verificação de integridade:

  • /healthz/ready para a verificação de preparação. A verificação de preparação filtra verificações de integridade para aqueles marcados com ready.
  • /healthz/live para a verificação de vida útil. A verificação de dinâmica filtra todas as verificações de integridade retornando false no HealthCheckOptions.Predicate delegado. Para obter mais informações sobre como filtrar verificações de integridade, consulte Filtrar verificações de integridade neste artigo.

Antes da conclusão da tarefa de inicialização, o /healthz/ready ponto de extremidade relata um Unhealthy status. Depois que a tarefa de inicialização for concluída, esse ponto de extremidade relatará um Healthy status. O /healthz/live ponto de extremidade exclui todas as verificações e relata um Healthy status para todas as chamadas.

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 ser necessário para executar o trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade subjacente do banco de dados. 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: /healthz/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

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.

  2. Escreva um método de extensão com parâmetros que o aplicativo de consumo chama em seu método Program.cs. Considere o seguinte exemplo de verificação de integridade, que aceita arg1 e arg2 como parâmetros de construtor:

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);
    

    A assinatura anterior indica que a verificação de integridade requer dados personalizados 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 exemplo a seguir, o chamador especifica:

    • arg1: um ponto de dados inteiro para a verificação de integridade.
    • arg2: um argumento de cadeia de caracteres para a verificação de integridade.
    • name: um nome de verificação de integridade opcional. Se null, um valor padrão é usado.
    • failureStatus: um opcional HealthStatus, que é relatado para um status de falha. Se null, HealthStatus.Unhealthy é usado.
    • tags: uma coleção opcional IEnumerable<string> de marcas.
    public static class SampleHealthCheckBuilderExtensions
    {
        private const string DefaultName = "Sample";
    
        public static IHealthChecksBuilder AddSampleHealthCheck(
            this IHealthChecksBuilder healthChecksBuilder,
            int arg1,
            string arg2,
            string? name = null,
            HealthStatus? failureStatus = null,
            IEnumerable<string>? tags = default)
        {
            return healthChecksBuilder.Add(
                new HealthCheckRegistration(
                    name ?? DefaultName,
                    _ => new SampleHealthCheckWithArgs(arg1, arg2),
                    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. Esse processo é útil em um cenário de sistema de monitoramento de integridade baseado em push que espera que cada processo chame o sistema de monitoramento periodicamente para determinar a integridade.

HealthCheckPublisherOptions permitir que você defina:

  • Delay: o atraso inicial aplicado após o início do aplicativo antes da execução de IHealthCheckPublisher instâncias. O atraso é aplicado uma vez na inicialização e não se aplica a iterações posteriores. 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 editor 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.

O exemplo a seguir demonstra o layout de um editor de integridade:

public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            // ...
        }
        else
        {
            // ...
        }

        return Task.CompletedTask;
    }
}

A HealthCheckPublisherOptions classe fornece propriedades para configurar o comportamento do editor de verificação de integridade.

O exemplo a seguir registra um editor de verificação de integridade como um singleton e configura HealthCheckPublisherOptions:

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});

builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();

Observação

AspNetCore.Diagnostics.HealthChecks inclui editores para vários sistemas, incluindo o Application Insights.

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

Recursos adicionais

ASP.NET Core oferece middleware de verificações de integridade e bibliotecas para relatar a integridade dos componentes da infraestrutura do 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 vários 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 artigo. 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 README.md exemplo e as descrições de cenário neste artigo para obter detalhes sobre como usar o aplicativo de exemplo.

Pré-requisitos

As verificações de integridade normalmente são usadas com um serviço de monitoramento externo ou orquestrador de contêineres 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 o 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 de banco de dados verifica a integridade de uma conexão de banco de dados usando .AspNetCore.Diagnostics.HealthChecks O cenário de investigação DbContext verifica um banco de dados usando um EF CoreDbContext. Para explorar os cenários de banco de dados, o aplicativo de exemplo:

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido ou 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 Properties/launchSettings.json arquivo que inclua 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 será considerado íntegro se puder responder na URL do ponto de extremidade de integridade. O gravador de resposta padrão grava o status (HealthStatus) como uma resposta de texto sem formatação para o cliente, indicando um HealthStatus.Healthy, HealthStatus.Degradedou HealthStatus.Unhealthy status.

Registre os serviços de verificação de integridade com AddHealthChecks em Startup.ConfigureServices. Crie um ponto de extremidade de verificação de integridade chamandoMapHealthChecks.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ção de integridade é colocada no CheckHealthAsync método. O exemplo a trueseguir define uma variável fictícia como healthCheckResultHealthy. 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 CheckHealthAsync gerar uma exceção durante a verificação, uma nova HealthReportEntry será retornada com seu HealthReportEntry.Status conjunto para o FailureStatus, que é definido pela 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 conjunto é 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 comAddCheck: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 é definido como null (padrão), HealthStatus.Unhealthy é 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 passadas 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

Em Startup.Configure, chame MapHealthChecks o 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 de verificações de integridade manualmente de um navegador não seja um cenário de uso comum, o Middleware CORS pode ser habilitado chamando RequireCors pontos de extremidade de verificação de integridade. Uma RequireCors sobrecarga aceita um representante do construtor de políticas CORS (CorsPolicyBuilder) ou um nome de política. Se uma política não for fornecida, a política padrão do CORS será usada. Para obter mais informações, consulte Habilitar 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" });

In Startup.Configure, o Predicate filtro da verificação de integridade 'Barra'. Somente Foo e Baz executam:

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

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

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

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

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 CustomWriterStartup.csde pré-processador para habilitar a Newtonsoft.Json versão de WriteResponse.

A API de verificações de integridade não fornece suporte interno para formatos de retorno ON complexos JSporque 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 JSa serialização ON, System.Text.Jsonconsulte 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.HealthChecksuma 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.

Incluir 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 chamandoMapHealthChecks: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 ou suportado pela Microsoft.

Investigação de DbContext do Entity Framework Core

A DbContext verificação confirma se o aplicativo pode se comunicar com o banco de dados configurado para um EF CoreDbContext. 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 método de CanConnectAsync chamadasEF 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 em 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 chamandoMapHealthChecks: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, um par de verificações de integridade é usado para distinguir 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 dinâmica 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 porque o aplicativo pode tentar baixar o arquivo várias vezes. Usamos uma investigação de vida para descrever a vida útil do processo, nenhuma outra verificação é executada. Também queremos impedir que as solicitações sejam enviadas ao aplicativo antes que o download do arquivo de configuração tenha sido 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. Expõe StartupHostedServiceHealthCheck uma propriedade, StartupTaskCompletedque o serviço hospedado pode definir true quando sua tarefa de longa execução for 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 ao chamar MapHealthChecksStartup.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 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 valor 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 Health Check Publisher (IHealthCheckPublisher implementação) 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 ser necessário para executar o trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade subjacente do banco de dados. 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). As HealthCheckResult informações do GC (Coletor de Lixo) incluem 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 aplicativo de exemplo:

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

Um ponto de extremidade de verificação de integridade é criado ao chamar MapHealthChecksStartup.Configure. Um WriteResponse delegado é fornecido à ResponseWriter propriedade para gerar uma resposta ON personalizada JSquando a verificação de integridade é executada:

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

O WriteResponse delegado formata em CompositeHealthCheckResult um JSobjeto ON e gera JSsaída ON para a resposta de verificação de integridade. 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 integridade baseados em métrica, incluindo armazenamento em disco e verificações de vida de valor máximo.

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

Filtrar por porta

MapHealthChecks Chame RequireHost com um padrão de URL que especifica uma porta para restringir solicitações de verificação de integridade à porta especificada. Essa abordagem normalmente é usada em um ambiente de contêiner para expor uma porta para 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 launchSettings.json arquivo 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 o launchSettings.json arquivo em uma Properties pasta.

O arquivo Properties/launchSettings.json a seguir no aplicativo de exemplo não está incluído nos arquivos de projeto do aplicativo de exemplo e 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 integridade chamando MapHealthChecksStartup.Configure.

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

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

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

  • 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 launchSettings.json arquivo no aplicativo de exemplo definindo a porta de gerenciamento explicitamente no código. No local em Program.cs que ele HostBuilder é criado, adicione uma chamada ListenAnyIP e forneça o ponto de extremidade da porta de gerenciamento do aplicativo. De Configure , especifique a porta de ManagementPortStartup.csgerenciamento 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 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 é tratado.

    Quando ocorre uma AccessViolationException ocorrência, ela FailureStatus é retornada com o HealthCheckResult para permitir que os usuários configurem o status de falha de verificação de integridade.

    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, HealthStatus.Unhealthy é relatado para 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 após o início do aplicativo antes da execução de 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 editor 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.

No aplicativo de exemplo, ReadinessPublisher é uma implementação IHealthCheckPublisher. O status da verificação de integridade é 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.HealthChecks inclui editores para vários sistemas, incluindo o Application Insights.

AspNetCore.Diagnostics.HealthChecks não é mantido ou 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, 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.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

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

ASP.NET Core oferece middleware de verificações de integridade e bibliotecas para relatar a integridade dos componentes da infraestrutura do 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 vários 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 artigo. 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 README.md exemplo e as descrições de cenário neste artigo para obter detalhes sobre como usar o aplicativo de exemplo.

Pré-requisitos

Verificações de integridade normalmente são usadas com um serviço de monitoramento externo ou orquestrador de contêiner 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 o 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 integridade de uma conexão de banco de dados usando .AspNetCore.Diagnostics.HealthChecks O cenário de investigação DbContext verifica um banco de dados usando um EF CoreDbContext. Para explorar os cenários de banco de dados, o aplicativo de exemplo:

Observação

AspNetCore.Diagnostics.HealthChecks não é mantido ou 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 Properties/launchSettings.json arquivo que inclua 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 será considerado íntegro se puder responder na URL do ponto de extremidade de integridade. O gravador de resposta padrão grava o status (HealthStatus) como uma resposta de texto sem formatação de volta para o cliente, indicando um HealthStatus.Healthy, HealthStatus.Degradedou HealthStatus.Unhealthy status.

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 MapHealthChecksStartup.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ção de integridade é colocada no CheckHealthAsync método. O exemplo a seguir define uma variável fictícia, healthCheckResultHealthycomo true. Se o valor for healthCheckResultHealthy definido como false, o HealthCheckResult.Unhealthy 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(
            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 integridade comAddCheck: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 é definido como null (padrão), HealthStatus.Unhealthy é 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" });

Chamar 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 o roteamento de verificações de integridade

In Startup.Configure, call MapHealthChecks on the endpoint builder with the endpoint URL or relative path:

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 da 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 executar verificações de integridade manualmente de um navegador não seja um cenário de uso comum, o Middleware CORS pode ser habilitado chamando RequireCors pontos de extremidade de verificação de integridade. Uma RequireCors sobrecarga aceita um representante do construtor de políticas cors (CorsPolicyBuilder) ou um nome de política. Se uma política não for fornecida, a política de CORS padrão será usada. Para obter mais informações, consulte Habilitar SOLICITAções de Origem Cruzada (CORS) em 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" });

In Startup.Configure, os Predicate filtros da verificação de integridade 'Barra'. Apenas Foo e Baz executam:

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

In Startup.Configure, set the option HealthCheckOptions.ResponseWriter to a delegate for writing the response:

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

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

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 CustomWriterStartup.csde pré-processador para habilitar a Newtonsoft.Json versão de WriteResponse.

A API de verificações de integridade não fornece suporte interno para formatos de retorno ON complexos JSporque 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 JSserialização ON 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.HealthChecksuma 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.

Incluir uma referência de pacote a 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 chamandoMapHealthChecks: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 ou suportado pela Microsoft.

Investigação de DbContext do Entity Framework Core

A DbContext verificação confirma que o aplicativo pode se comunicar com o banco de dados configurado para um EF CoreDbContext. 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 método de chamadasEF Core.CanConnectAsync 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 em 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 chamandoMapHealthChecks: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, um par de verificações de integridade é usado para distinguir 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 dinâmica 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 porque o aplicativo pode tentar baixar novamente o arquivo várias vezes. Usamos uma investigação de dinâmica para descrever a dinâmica do processo, nenhuma outra verificação é executada. Também queremos impedir que as solicitações sejam enviadas ao aplicativo antes que o download do arquivo de configuração tenha êxito. 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. Expõe StartupHostedServiceHealthCheck uma propriedade, StartupTaskCompletedque o serviço hospedado pode definir true quando sua tarefa de execução longa for 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 do 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 chamandoMapHealthChecks.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 vida útil. A verificação de dinâmica filtra o StartupHostedServiceHealthCheck retornando false no HealthCheckOptions.Predicate (para obter mais informações, consulte Verificações de integridade do filtro)

No seguinte código de exemplo:

  • 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 Health Check Publisher (IHealthCheckPublisher implementação) 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 ser necessário para executar o trabalho de inicialização demorado antes de aceitar solicitações, como um teste da disponibilidade subjacente do banco de dados. 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). As HealthCheckResult informações do GC (Coletor de Lixo) incluem 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 aplicativo de exemplo:

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

Um ponto de extremidade de verificação de integridade é criado chamandoMapHealthChecks.Startup.Configure Um WriteResponse delegado é fornecido à ResponseWriter propriedade para gerar uma resposta ON personalizada JSquando a verificação de integridade é executada:

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

O WriteResponse delegado formata em CompositeHealthCheckResult um JSobjeto ON e gera JSsaída ON para a resposta de verificação de integridade. 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 integridade baseados em métrica, incluindo armazenamento em disco e verificações de vida de valor máximo.

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

Filtrar por porta

MapHealthChecks Chame RequireHost com um padrão de URL que especifica uma porta para restringir solicitações de verificação de integridade à porta especificada. Essa abordagem normalmente é usada em um ambiente de contêiner para expor uma porta para 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 launchSettings.json arquivo 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 o launchSettings.json arquivo em uma Properties pasta.

O arquivo Properties/launchSettings.json a seguir no aplicativo de exemplo não está incluído nos arquivos de projeto do aplicativo de exemplo e 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 integridade chamando MapHealthChecksStartup.Configure.

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

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

Os pontos de extremidade são criados no aplicativo de exemplo em 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 valor 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 launchSettings.json arquivo no aplicativo de exemplo definindo a porta de gerenciamento explicitamente no código. No local em Program.cs que ele HostBuilder é criado, adicione uma chamada ListenAnyIP e forneça o ponto de extremidade da porta de gerenciamento do aplicativo. Além Configure disso, especifique a porta de ManagementPortStartup.csgerenciamento 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 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 é tratado.

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

    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, HealthStatus.Unhealthy é relatado para 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 após o início do aplicativo antes da execução de 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 editor 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.

No aplicativo de exemplo, ReadinessPublisher é uma implementação IHealthCheckPublisher. O status de verificação de integridade é 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.HealthChecks inclui editores para vários sistemas, incluindo o Application Insights.

AspNetCore.Diagnostics.HealthChecks não é mantido ou 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, 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.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

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