Merge pull request #456 from dotnet-maestro-bot/merge/release/2.2-to-master
[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
commit
a59765c472
|
|
@ -16,6 +16,7 @@
|
||||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-alpha1-10173</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||||
|
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-alpha1-10173</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// Pass in `--scenario basic` at the command line to run this sample.
|
||||||
|
public class BasicStartup
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Registers required services for health checks
|
||||||
|
services.AddHealthChecks();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
// This will register the health checks middleware at the URL /health.
|
||||||
|
//
|
||||||
|
// By default health checks will return a 200 with 'Healthy'.
|
||||||
|
// - No health checks are registered by default, the app is healthy if it is reachable
|
||||||
|
// - The default response writer writes the HealthCheckStatus as text/plain content
|
||||||
|
//
|
||||||
|
// This is the simplest way to use health checks, it is suitable for systems
|
||||||
|
// that want to check for 'liveness' of an application.
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Go to /health to see the health status");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// Pass in `--scenario writer` at the command line to run this sample.
|
||||||
|
public class CustomWriterStartup
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Registers required services for health checks
|
||||||
|
services.AddHealthChecks();
|
||||||
|
|
||||||
|
// This is an example of registering a custom health check as a service.
|
||||||
|
// All IHealthCheck services will be available to the health check service and
|
||||||
|
// middleware.
|
||||||
|
//
|
||||||
|
// We recommend registering all health checks as Singleton services.
|
||||||
|
services.AddSingleton<IHealthCheck, GCInfoHealthCheck>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
// This will register the health checks middleware at the URL /health
|
||||||
|
//
|
||||||
|
// This example overrides the HealthCheckResponseWriter to write the health
|
||||||
|
// check result in a totally custom way.
|
||||||
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
// This custom writer formats the detailed status as an HTML table.
|
||||||
|
ResponseWriter = WriteResponse,
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Go to /health to see the health status");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task WriteResponse(HttpContext httpContext, CompositeHealthCheckResult result)
|
||||||
|
{
|
||||||
|
httpContext.Response.ContentType = "text/html";
|
||||||
|
return httpContext.Response.WriteAsync($@"
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
Everything is {result.Status}
|
||||||
|
</h1>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><td>Name</td><td>Status</td></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{string.Join("", result.Results.Select(kvp => $"<tr><td>{kvp.Key}</td><td>{kvp.Value.Status}</td></tr>"))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// Pass in `--scenario detailed` at the command line to run this sample.
|
||||||
|
public class DetailedStatusStartup
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Registers required services for health checks
|
||||||
|
services
|
||||||
|
.AddHealthChecks()
|
||||||
|
|
||||||
|
// Registers a custom health check, in this case it will execute an
|
||||||
|
// inline delegate.
|
||||||
|
.AddCheck("GC Info", () =>
|
||||||
|
{
|
||||||
|
// This example will report degraded status if the application is using
|
||||||
|
// more than 1gb of memory.
|
||||||
|
//
|
||||||
|
// Additionally we include some GC info in the reported diagnostics.
|
||||||
|
var allocated = GC.GetTotalMemory(forceFullCollection: false);
|
||||||
|
var data = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "Allocated", allocated },
|
||||||
|
{ "Gen0Collections", GC.CollectionCount(0) },
|
||||||
|
{ "Gen1Collections", GC.CollectionCount(1) },
|
||||||
|
{ "Gen2Collections", GC.CollectionCount(2) },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Report degraded status if the allocated memory is >= 1gb (in bytes)
|
||||||
|
var status = allocated >= 1024 * 1024 * 1024 ? HealthCheckStatus.Degraded : HealthCheckStatus.Healthy;
|
||||||
|
|
||||||
|
return Task.FromResult(new HealthCheckResult(
|
||||||
|
status,
|
||||||
|
exception: null,
|
||||||
|
description: "reports degraded status if allocated bytes >= 1gb",
|
||||||
|
data: data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
// This will register the health checks middleware at the URL /health
|
||||||
|
//
|
||||||
|
// This example overrides the ResponseWriter to include a detailed
|
||||||
|
// status as JSON. Use this response writer (or create your own) to include
|
||||||
|
// detailed diagnostic information for use by a monitoring system.
|
||||||
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
ResponseWriter = HealthCheckResponseWriters.WriteDetailedJson,
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Go to /health to see the health status");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// This is an example of a custom health check that implements IHealthCheck.
|
||||||
|
// This is the same core logic as the DetailedStatusStartup example.
|
||||||
|
// See CustomWriterStartup to see how this is registered.
|
||||||
|
public class GCInfoHealthCheck : IHealthCheck
|
||||||
|
{
|
||||||
|
public string Name { get; } = "GCInfo";
|
||||||
|
|
||||||
|
public Task<HealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
// This example will report degraded status if the application is using
|
||||||
|
// more than 1gb of memory.
|
||||||
|
//
|
||||||
|
// Additionally we include some GC info in the reported diagnostics.
|
||||||
|
var allocated = GC.GetTotalMemory(forceFullCollection: false);
|
||||||
|
var data = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "Allocated", allocated },
|
||||||
|
{ "Gen0Collections", GC.CollectionCount(0) },
|
||||||
|
{ "Gen1Collections", GC.CollectionCount(1) },
|
||||||
|
{ "Gen2Collections", GC.CollectionCount(2) },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Report degraded status if the allocated memory is >= 1gb (in bytes)
|
||||||
|
var status = allocated >= 1024 * 1024 * 1024 ? HealthCheckStatus.Degraded : HealthCheckStatus.Healthy;
|
||||||
|
|
||||||
|
return Task.FromResult(new HealthCheckResult(
|
||||||
|
status,
|
||||||
|
exception: null,
|
||||||
|
description: "reports degraded status if allocated bytes >= 1gb",
|
||||||
|
data: data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<!-- Used in our tests -->
|
||||||
|
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">netcoreapp2.0;net461</TargetFrameworks>
|
||||||
|
<TargetFrameworks Condition="'$(TargetFrameworks)'==''">netcoreapp2.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// Pass in `--scenario liveness` at the command line to run this sample.
|
||||||
|
public class LivenessProbeStartup
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// Registers required services for health checks
|
||||||
|
services
|
||||||
|
.AddHealthChecks()
|
||||||
|
.AddCheck("identity", () => Task.FromResult(HealthCheckResult.Healthy()))
|
||||||
|
.AddCheck(new SlowDependencyHealthCheck());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
// This will register the health checks middleware twice:
|
||||||
|
// - at /health/ready for 'readiness'
|
||||||
|
// - at /health/live for 'liveness'
|
||||||
|
//
|
||||||
|
// Using a separate liveness and readiness check is useful in an environment like Kubernetes
|
||||||
|
// when an application needs to do significant work before accepting requests. Using separate
|
||||||
|
// checks allows the orchestrator to distinguish whether the application is functioning but
|
||||||
|
// not yet ready or if the application has failed to start.
|
||||||
|
//
|
||||||
|
// For instance the liveness check will do a quick set of checks to determine if the process
|
||||||
|
// is functioning correctly.
|
||||||
|
//
|
||||||
|
// The readiness check might do a set of more expensive or time-consuming checks to determine
|
||||||
|
// if all other resources are responding.
|
||||||
|
//
|
||||||
|
// See https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ for
|
||||||
|
// more details about readiness and liveness probes in Kubernetes.
|
||||||
|
//
|
||||||
|
// In this example, the liveness check will us an 'identity' check that always returns healthy.
|
||||||
|
//
|
||||||
|
// In this example, the readiness check will run all registered checks, include a check with an
|
||||||
|
// long initialization time (15 seconds).
|
||||||
|
|
||||||
|
|
||||||
|
// The readiness check uses all of the registered health checks (default)
|
||||||
|
app.UseHealthChecks("/health/ready", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
// This sample is using detailed status to make more apparent which checks are being run - any
|
||||||
|
// output format will work with liveness and readiness checks.
|
||||||
|
ResponseWriter = HealthCheckResponseWriters.WriteDetailedJson,
|
||||||
|
});
|
||||||
|
|
||||||
|
// The liveness check uses an 'identity' health check that always returns healty
|
||||||
|
app.UseHealthChecks("/health/live", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
// Filters the set of health checks run by this middleware
|
||||||
|
HealthCheckNames =
|
||||||
|
{
|
||||||
|
"identity",
|
||||||
|
},
|
||||||
|
|
||||||
|
// This sample is using detailed status to make more apparent which checks are being run - any
|
||||||
|
// output format will work with liveness and readiness checks.
|
||||||
|
ResponseWriter = HealthCheckResponseWriters.WriteDetailedJson,
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Go to /health/ready to see the readiness status");
|
||||||
|
await context.Response.WriteAsync(Environment.NewLine);
|
||||||
|
await context.Response.WriteAsync("Go to /health/live to see the liveness status");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace HealthChecksSample
|
namespace HealthChecksSample
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
|
private static readonly Dictionary<string, Type> _scenarios;
|
||||||
|
|
||||||
|
static Program()
|
||||||
|
{
|
||||||
|
_scenarios = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
{ "", typeof(BasicStartup) },
|
||||||
|
{ "basic", typeof(BasicStartup) },
|
||||||
|
{ "detailed", typeof(DetailedStatusStartup) },
|
||||||
|
{ "writer", typeof(CustomWriterStartup) },
|
||||||
|
{ "liveness", typeof(LivenessProbeStartup) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
BuildWebHost(args).Run();
|
BuildWebHost(args).Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IWebHost BuildWebHost(string[] args) =>
|
public static IWebHost BuildWebHost(string[] args)
|
||||||
new WebHostBuilder()
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
|
||||||
|
.AddCommandLine(args)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var scenario = config["scenario"] ?? string.Empty;
|
||||||
|
if (!_scenarios.TryGetValue(scenario, out var startupType))
|
||||||
|
{
|
||||||
|
startupType = typeof(BasicStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WebHostBuilder()
|
||||||
|
.UseConfiguration(config)
|
||||||
.ConfigureLogging(builder =>
|
.ConfigureLogging(builder =>
|
||||||
{
|
{
|
||||||
builder.AddConsole();
|
builder.AddConsole();
|
||||||
})
|
})
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
.UseStartup<Startup>()
|
.UseStartup(startupType)
|
||||||
.Build();
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
|
namespace HealthChecksSample
|
||||||
|
{
|
||||||
|
// Simulates a health check for an application dependency that takes a while to initialize.
|
||||||
|
// This is part of the readiness/liveness probe sample.
|
||||||
|
public class SlowDependencyHealthCheck : IHealthCheck
|
||||||
|
{
|
||||||
|
public static readonly string HealthCheckName = "slow_dependency";
|
||||||
|
|
||||||
|
private readonly Task _task;
|
||||||
|
|
||||||
|
public SlowDependencyHealthCheck()
|
||||||
|
{
|
||||||
|
_task = Task.Delay(15 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name => HealthCheckName;
|
||||||
|
|
||||||
|
public Task<HealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
if (_task.IsCompleted)
|
||||||
|
{
|
||||||
|
return Task.FromResult(HealthCheckResult.Healthy("Dependency is ready"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(HealthCheckResult.Unhealthy("Dependency is still initializing"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace HealthChecksSample
|
|
||||||
{
|
|
||||||
public class Startup
|
|
||||||
{
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
|
||||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddHealthChecks();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
|
||||||
{
|
|
||||||
app.UseHealthChecks("/health");
|
|
||||||
|
|
||||||
app.Run(async (context) =>
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Hello World!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Builder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="IApplicationBuilder"/> extension methods for the <see cref="HealthCheckMiddleware"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class HealthCheckApplicationBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a middleware that provides health check status.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||||
|
/// <param name="path">The path on which to provide health check status.</param>
|
||||||
|
/// <returns>A reference to the <paramref name="app"/> after the operation has completed.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// The health check middleware will use default settings other than the provided <paramref name="path"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static IApplicationBuilder UseHealthChecks(this IApplicationBuilder app, PathString path)
|
||||||
|
{
|
||||||
|
if (app == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(app));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path.HasValue)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("A URL path must be provided", nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.Map(path, b => b.UseMiddleware<HealthCheckMiddleware>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a middleware that provides health check status.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
||||||
|
/// <param name="path">The path on which to provide health check status.</param>
|
||||||
|
/// <param name="options">A <see cref="HealthCheckOptions"/> used to configure the middleware.</param>
|
||||||
|
/// <returns>A reference to the <paramref name="app"/> after the operation has completed.</returns>
|
||||||
|
public static IApplicationBuilder UseHealthChecks(this IApplicationBuilder app, PathString path, HealthCheckOptions options)
|
||||||
|
{
|
||||||
|
if (app == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(app));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path.HasValue)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("A URL path must be provided", nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.Map(path, b => b.UseMiddleware<HealthCheckMiddleware>(Options.Create(options)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="IApplicationBuilder"/> extension methods for the <see cref="HealthCheckMiddleware"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class HealthCheckAppBuilderExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a middleware that provides a REST API for requesting health check status.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
|
|
||||||
/// <param name="path">The path on which to provide the API.</param>
|
|
||||||
/// <returns>A reference to the <paramref name="app"/> after the operation has completed.</returns>
|
|
||||||
public static IApplicationBuilder UseHealthChecks(this IApplicationBuilder app, PathString path)
|
|
||||||
{
|
|
||||||
app = app ?? throw new ArgumentNullException(nameof(app));
|
|
||||||
|
|
||||||
return app.UseMiddleware<HealthCheckMiddleware>(Options.Create(new HealthCheckOptions()
|
|
||||||
{
|
|
||||||
Path = path
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,14 +2,12 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
{
|
{
|
||||||
|
|
@ -18,62 +16,103 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly HealthCheckOptions _healthCheckOptions;
|
private readonly HealthCheckOptions _healthCheckOptions;
|
||||||
private readonly IHealthCheckService _healthCheckService;
|
private readonly IHealthCheckService _healthCheckService;
|
||||||
|
private readonly IHealthCheck[] _checks;
|
||||||
|
|
||||||
public HealthCheckMiddleware(RequestDelegate next, IOptions<HealthCheckOptions> healthCheckOptions, IHealthCheckService healthCheckService)
|
public HealthCheckMiddleware(
|
||||||
|
RequestDelegate next,
|
||||||
|
IOptions<HealthCheckOptions> healthCheckOptions,
|
||||||
|
IHealthCheckService healthCheckService)
|
||||||
{
|
{
|
||||||
|
if (next == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(next));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (healthCheckOptions == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(healthCheckOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (healthCheckService == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(healthCheckService));
|
||||||
|
}
|
||||||
|
|
||||||
_next = next;
|
_next = next;
|
||||||
_healthCheckOptions = healthCheckOptions.Value;
|
_healthCheckOptions = healthCheckOptions.Value;
|
||||||
_healthCheckService = healthCheckService;
|
_healthCheckService = healthCheckService;
|
||||||
|
|
||||||
|
_checks = FilterHealthChecks(_healthCheckService.Checks, healthCheckOptions.Value.HealthCheckNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Process an individual request.
|
/// Processes a request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="httpContext"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext httpContext)
|
||||||
{
|
{
|
||||||
if (context.Request.Path == _healthCheckOptions.Path)
|
if (httpContext == null)
|
||||||
{
|
{
|
||||||
// Get results
|
throw new ArgumentNullException(nameof(httpContext));
|
||||||
var result = await _healthCheckService.CheckHealthAsync(context.RequestAborted);
|
}
|
||||||
|
|
||||||
// Map status to response code
|
// Get results
|
||||||
switch (result.Status)
|
var result = await _healthCheckService.CheckHealthAsync(_checks, httpContext.RequestAborted);
|
||||||
|
|
||||||
|
// Map status to response code - this is customizable via options.
|
||||||
|
if (!_healthCheckOptions.ResultStatusCodes.TryGetValue(result.Status, out var statusCode))
|
||||||
|
{
|
||||||
|
var message =
|
||||||
|
$"No status code mapping found for {nameof(HealthCheckStatus)} value: {result.Status}." +
|
||||||
|
$"{nameof(HealthCheckOptions)}.{nameof(HealthCheckOptions.ResultStatusCodes)} must contain" +
|
||||||
|
$"an entry for {result.Status}.";
|
||||||
|
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContext.Response.StatusCode = statusCode;
|
||||||
|
|
||||||
|
if (_healthCheckOptions.ResponseWriter != null)
|
||||||
|
{
|
||||||
|
await _healthCheckOptions.ResponseWriter(httpContext, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IHealthCheck[] FilterHealthChecks(
|
||||||
|
IReadOnlyDictionary<string, IHealthCheck> checks,
|
||||||
|
ISet<string> names)
|
||||||
|
{
|
||||||
|
// If there are no filters then include all checks.
|
||||||
|
if (names.Count == 0)
|
||||||
|
{
|
||||||
|
return checks.Values.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of what we don't find so we can report errors.
|
||||||
|
var notFound = new HashSet<string>(names, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var matches = new List<IHealthCheck>();
|
||||||
|
|
||||||
|
foreach (var kvp in checks)
|
||||||
|
{
|
||||||
|
if (!notFound.Remove(kvp.Key))
|
||||||
{
|
{
|
||||||
case HealthCheckStatus.Failed:
|
// This check was excluded
|
||||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
continue;
|
||||||
break;
|
|
||||||
case HealthCheckStatus.Unhealthy:
|
|
||||||
context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
|
|
||||||
break;
|
|
||||||
case HealthCheckStatus.Degraded:
|
|
||||||
// Degraded doesn't mean unhealthy so we return 200, but the content will contain more details
|
|
||||||
context.Response.StatusCode = StatusCodes.Status200OK;
|
|
||||||
break;
|
|
||||||
case HealthCheckStatus.Healthy:
|
|
||||||
context.Response.StatusCode = StatusCodes.Status200OK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// This will only happen when we change HealthCheckStatus and we don't update this.
|
|
||||||
Debug.Fail($"Unrecognized HealthCheckStatus value: {result.Status}");
|
|
||||||
throw new InvalidOperationException($"Unrecognized HealthCheckStatus value: {result.Status}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render results to JSON
|
matches.Add(kvp.Value);
|
||||||
var json = new JObject(
|
|
||||||
new JProperty("status", result.Status.ToString()),
|
|
||||||
new JProperty("results", new JObject(result.Results.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))))))))));
|
|
||||||
await context.Response.WriteAsync(json.ToString(Formatting.None));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (notFound.Count > 0)
|
||||||
{
|
{
|
||||||
await _next(context);
|
var message =
|
||||||
|
$"The following health checks were not found: '{string.Join(", ", notFound)}'. " +
|
||||||
|
$"Registered health checks: '{string.Join(", ", checks.Keys)}'.";
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return matches.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
{
|
{
|
||||||
|
|
@ -11,8 +15,32 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
public class HealthCheckOptions
|
public class HealthCheckOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the path at which the Health Check results will be available.
|
/// Gets a set of health check names used to filter the set of health checks run.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PathString Path { get; set; }
|
/// <remarks>
|
||||||
|
/// If <see cref="HealthCheckNames"/> is empty, the <see cref="HealthCheckMiddleware"/> will run all
|
||||||
|
/// registered health checks - this is the default behavior. To run a subset of health checks,
|
||||||
|
/// add the names of the desired health checks.
|
||||||
|
/// </remarks>
|
||||||
|
public ISet<string> HealthCheckNames { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public IDictionary<HealthCheckStatus, int> ResultStatusCodes { get; } = new Dictionary<HealthCheckStatus, int>()
|
||||||
|
{
|
||||||
|
{ HealthCheckStatus.Healthy, StatusCodes.Status200OK },
|
||||||
|
{ HealthCheckStatus.Degraded, StatusCodes.Status200OK },
|
||||||
|
{ HealthCheckStatus.Unhealthy, StatusCodes.Status503ServiceUnavailable },
|
||||||
|
|
||||||
|
// This means that a health check failed, so 500 is appropriate. This is an error.
|
||||||
|
{ HealthCheckStatus.Failed, StatusCodes.Status500InternalServerError },
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a delegate used to write the response.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The default value is a delegate that will write a minimal <c>text/plain</c> response with the value
|
||||||
|
/// of <see cref="CompositeHealthCheckResult.Status"/> as a string.
|
||||||
|
/// </remarks>
|
||||||
|
public Func<HttpContext, CompositeHealthCheckResult, Task> ResponseWriter { get; set; } = HealthCheckResponseWriters.WriteMinimalPlaintext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
|
{
|
||||||
|
public static class HealthCheckResponseWriters
|
||||||
|
{
|
||||||
|
public static Task WriteMinimalPlaintext(HttpContext httpContext, CompositeHealthCheckResult result)
|
||||||
|
{
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(httpContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContext.Response.ContentType = "text/plain";
|
||||||
|
return httpContext.Response.WriteAsync(result.Status.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task WriteDetailedJson(HttpContext httpContext, CompositeHealthCheckResult result)
|
||||||
|
{
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(httpContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContext.Response.ContentType = "application/json";
|
||||||
|
|
||||||
|
var json = new JObject(
|
||||||
|
new JProperty("status", result.Status.ToString()),
|
||||||
|
new JProperty("results", new JObject(result.Results.Select(pair =>
|
||||||
|
new JProperty(pair.Key, new JObject(
|
||||||
|
new JProperty("status", pair.Value.Status.ToString()),
|
||||||
|
new JProperty("description", pair.Value.Description),
|
||||||
|
new JProperty("data", new JObject(pair.Value.Data.Select(p => new JProperty(p.Key, p.Value))))))))));
|
||||||
|
return httpContext.Response.WriteAsync(json.ToString(Formatting.Indented));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,115 +1,5 @@
|
||||||
{
|
{
|
||||||
"AssemblyIdentity": "Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
"AssemblyIdentity": "Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||||
"Types": [
|
"Types": [
|
||||||
{
|
|
||||||
"Name": "Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckMiddleware",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "InvokeAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "context",
|
|
||||||
"Type": "Microsoft.AspNetCore.Http.HttpContext"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "next",
|
|
||||||
"Type": "Microsoft.AspNetCore.Http.RequestDelegate"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "healthCheckOptions",
|
|
||||||
"Type": "Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "healthCheckService",
|
|
||||||
"Type": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Path",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.AspNetCore.Http.PathString",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "set_Path",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "value",
|
|
||||||
"Type": "Microsoft.AspNetCore.Http.PathString"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Void",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.AspNetCore.Builder.HealthCheckAppBuilderExtensions",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"Abstract": true,
|
|
||||||
"Static": true,
|
|
||||||
"Sealed": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "UseHealthChecks",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "app",
|
|
||||||
"Type": "Microsoft.AspNetCore.Builder.IApplicationBuilder"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "path",
|
|
||||||
"Type": "Microsoft.AspNetCore.Http.PathString"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.AspNetCore.Builder.IApplicationBuilder",
|
|
||||||
"Static": true,
|
|
||||||
"Extension": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,377 +1,5 @@
|
||||||
{
|
{
|
||||||
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||||
"Types": [
|
"Types": [
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Struct",
|
|
||||||
"Sealed": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Status",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckStatus",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Exception",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.Exception",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Description",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.String",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Data",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Healthy",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Healthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Healthy",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult",
|
|
||||||
"Static": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "status",
|
|
||||||
"Type": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckStatus"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "exception",
|
|
||||||
"Type": "System.Exception"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "description",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "data",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, System.Object>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckStatus",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Enumeration",
|
|
||||||
"Sealed": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Field",
|
|
||||||
"Name": "Unknown",
|
|
||||||
"Parameters": [],
|
|
||||||
"GenericParameter": [],
|
|
||||||
"Literal": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Field",
|
|
||||||
"Name": "Failed",
|
|
||||||
"Parameters": [],
|
|
||||||
"GenericParameter": [],
|
|
||||||
"Literal": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Field",
|
|
||||||
"Name": "Unhealthy",
|
|
||||||
"Parameters": [],
|
|
||||||
"GenericParameter": [],
|
|
||||||
"Literal": "2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Field",
|
|
||||||
"Name": "Degraded",
|
|
||||||
"Parameters": [],
|
|
||||||
"GenericParameter": [],
|
|
||||||
"Literal": "3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Field",
|
|
||||||
"Name": "Healthy",
|
|
||||||
"Parameters": [],
|
|
||||||
"GenericParameter": [],
|
|
||||||
"Literal": "4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Interface",
|
|
||||||
"Abstract": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Name",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.String",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -11,15 +11,10 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks
|
||||||
/// A simple implementation of <see cref="IHealthCheck"/> which uses a provided delegate to
|
/// A simple implementation of <see cref="IHealthCheck"/> which uses a provided delegate to
|
||||||
/// implement the check.
|
/// implement the check.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HealthCheck : IHealthCheck
|
public sealed class HealthCheck : IHealthCheck
|
||||||
{
|
{
|
||||||
private readonly Func<CancellationToken, Task<HealthCheckResult>> _check;
|
private readonly Func<CancellationToken, Task<HealthCheckResult>> _check;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the health check, which should indicate the component being checked.
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an instance of <see cref="HealthCheck"/> from the specified <paramref name="name"/> and <paramref name="check"/>.
|
/// Create an instance of <see cref="HealthCheck"/> from the specified <paramref name="name"/> and <paramref name="check"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -27,10 +22,15 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks
|
||||||
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
|
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
|
||||||
public HealthCheck(string name, Func<CancellationToken, Task<HealthCheckResult>> check)
|
public HealthCheck(string name, Func<CancellationToken, Task<HealthCheckResult>> check)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
_check = check;
|
_check = check ?? throw new ArgumentNullException(nameof(check));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the health check, which should indicate the component being checked.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs the health check, returning the status of the component being checked.
|
/// Runs the health check, returning the status of the component being checked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,22 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
|
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
|
||||||
public static IHealthChecksBuilder AddCheck(this IHealthChecksBuilder builder, string name, Func<CancellationToken, Task<HealthCheckResult>> check)
|
public static IHealthChecksBuilder AddCheck(this IHealthChecksBuilder builder, string name, Func<CancellationToken, Task<HealthCheckResult>> check)
|
||||||
{
|
{
|
||||||
builder.Services.AddSingleton<IHealthCheck>(services => new HealthCheck(name, check));
|
if (builder == null)
|
||||||
return builder;
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(check));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.AddCheck(new HealthCheck(name, check));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -33,7 +47,46 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
/// <param name="name">The name of the health check, which should indicate the component being checked.</param>
|
/// <param name="name">The name of the health check, which should indicate the component being checked.</param>
|
||||||
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
|
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
|
||||||
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
|
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
|
||||||
public static IHealthChecksBuilder AddCheck(this IHealthChecksBuilder builder, string name, Func<Task<HealthCheckResult>> check) =>
|
public static IHealthChecksBuilder AddCheck(this IHealthChecksBuilder builder, string name, Func<Task<HealthCheckResult>> check)
|
||||||
builder.AddCheck(name, _ => check());
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(check));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.AddCheck(name, _ => check());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new health check with the implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IHealthChecksBuilder"/> to add the check to.</param>
|
||||||
|
/// <param name="check">An <see cref="IHealthCheck"/> implementation.</param>
|
||||||
|
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns>
|
||||||
|
public static IHealthChecksBuilder AddCheck(this IHealthChecksBuilder builder, IHealthCheck check)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(check));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IHealthCheck>(check);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,334 +1,5 @@
|
||||||
{
|
{
|
||||||
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
"AssemblyIdentity": "Microsoft.Extensions.Diagnostics.HealthChecks, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||||
"Types": [
|
"Types": [
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.DependencyInjection.HealthChecksBuilderAddCheckExtensions",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"Abstract": true,
|
|
||||||
"Static": true,
|
|
||||||
"Sealed": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "AddCheck",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "builder",
|
|
||||||
"Type": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "name",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "check",
|
|
||||||
"Type": "System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder",
|
|
||||||
"Static": true,
|
|
||||||
"Extension": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "AddCheck",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "builder",
|
|
||||||
"Type": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "name",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "check",
|
|
||||||
"Type": "System.Func<System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder",
|
|
||||||
"Static": true,
|
|
||||||
"Extension": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.DependencyInjection.HealthCheckServiceCollectionExtensions",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"Abstract": true,
|
|
||||||
"Static": true,
|
|
||||||
"Sealed": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "AddHealthChecks",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "services",
|
|
||||||
"Type": "Microsoft.Extensions.DependencyInjection.IServiceCollection"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder",
|
|
||||||
"Static": true,
|
|
||||||
"Extension": true,
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.CompositeHealthCheckResult",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Results",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.Collections.Generic.IReadOnlyDictionary<System.String, Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Status",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckStatus",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "results",
|
|
||||||
"Type": "System.Collections.Generic.IReadOnlyDictionary<System.String, Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheck",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"ImplementedInterfaces": [
|
|
||||||
"Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck"
|
|
||||||
],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Name",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.String",
|
|
||||||
"Sealed": true,
|
|
||||||
"Virtual": true,
|
|
||||||
"ImplementedInterface": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>",
|
|
||||||
"Sealed": true,
|
|
||||||
"Virtual": true,
|
|
||||||
"ImplementedInterface": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "name",
|
|
||||||
"Type": "System.String"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "check",
|
|
||||||
"Type": "System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult>>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Class",
|
|
||||||
"ImplementedInterfaces": [
|
|
||||||
"Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService"
|
|
||||||
],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Checks",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.Collections.Generic.IReadOnlyDictionary<System.String, Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>",
|
|
||||||
"Sealed": true,
|
|
||||||
"Virtual": true,
|
|
||||||
"ImplementedInterface": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.CompositeHealthCheckResult>",
|
|
||||||
"Sealed": true,
|
|
||||||
"Virtual": true,
|
|
||||||
"ImplementedInterface": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "checks",
|
|
||||||
"Type": "System.Collections.Generic.IEnumerable<Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.CompositeHealthCheckResult>",
|
|
||||||
"Sealed": true,
|
|
||||||
"Virtual": true,
|
|
||||||
"ImplementedInterface": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "healthChecks",
|
|
||||||
"Type": "System.Collections.Generic.IEnumerable<Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Constructor",
|
|
||||||
"Name": ".ctor",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "healthChecks",
|
|
||||||
"Type": "System.Collections.Generic.IEnumerable<Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "logger",
|
|
||||||
"Type": "Microsoft.Extensions.Logging.ILogger<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService>"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Visibility": "Public",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Interface",
|
|
||||||
"Abstract": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Services",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "Microsoft.Extensions.DependencyInjection.IServiceCollection",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckService",
|
|
||||||
"Visibility": "Public",
|
|
||||||
"Kind": "Interface",
|
|
||||||
"Abstract": true,
|
|
||||||
"ImplementedInterfaces": [],
|
|
||||||
"Members": [
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "get_Checks",
|
|
||||||
"Parameters": [],
|
|
||||||
"ReturnType": "System.Collections.Generic.IReadOnlyDictionary<System.String, Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.CompositeHealthCheckResult>",
|
|
||||||
"GenericParameter": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Kind": "Method",
|
|
||||||
"Name": "CheckHealthAsync",
|
|
||||||
"Parameters": [
|
|
||||||
{
|
|
||||||
"Name": "checks",
|
|
||||||
"Type": "System.Collections.Generic.IEnumerable<Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "cancellationToken",
|
|
||||||
"Type": "System.Threading.CancellationToken",
|
|
||||||
"DefaultValue": "default(System.Threading.CancellationToken)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ReturnType": "System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.CompositeHealthCheckResult>",
|
|
||||||
"GenericParameter": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"GenericParameters": []
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
|
{
|
||||||
|
public class HealthCheckMiddlewareSampleTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task BasicStartup()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.UseStartup<HealthChecksSample.BasicStartup>();
|
||||||
|
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CustomWriterStartup()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.UseStartup<HealthChecksSample.CustomWriterStartup>();
|
||||||
|
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/html", response.Content.Headers.ContentType.ToString());
|
||||||
|
|
||||||
|
// Ignoring the body since it contains a bunch of statistics
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DetailedStatusStartup()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.UseStartup<HealthChecksSample.DetailedStatusStartup>();
|
||||||
|
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("application/json", response.Content.Headers.ContentType.ToString());
|
||||||
|
|
||||||
|
// Ignoring the body since it contains a bunch of statistics
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task LivenessProbeStartup_Liveness()
|
||||||
|
{
|
||||||
|
var expectedJson = JsonConvert.SerializeObject(new
|
||||||
|
{
|
||||||
|
status = "Healthy",
|
||||||
|
results = new
|
||||||
|
{
|
||||||
|
identity = new
|
||||||
|
{
|
||||||
|
status = "Healthy",
|
||||||
|
description = "",
|
||||||
|
data = new { }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, Formatting.Indented);
|
||||||
|
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.UseStartup<HealthChecksSample.LivenessProbeStartup>();
|
||||||
|
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health/live");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("application/json", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal(expectedJson, await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task LivenessProbeStartup_Readiness()
|
||||||
|
{
|
||||||
|
var expectedJson = JsonConvert.SerializeObject(new
|
||||||
|
{
|
||||||
|
status = "Unhealthy",
|
||||||
|
results = new
|
||||||
|
{
|
||||||
|
identity = new
|
||||||
|
{
|
||||||
|
status = "Healthy",
|
||||||
|
description = "",
|
||||||
|
data = new { }
|
||||||
|
},
|
||||||
|
slow_dependency = new
|
||||||
|
{
|
||||||
|
status = "Unhealthy",
|
||||||
|
description = "Dependency is still initializing",
|
||||||
|
data = new { }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, Formatting.Indented);
|
||||||
|
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.UseStartup<HealthChecksSample.LivenessProbeStartup>();
|
||||||
|
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health/ready");
|
||||||
|
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
|
||||||
|
Assert.Equal("application/json", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal(expectedJson, await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,10 +17,8 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
{
|
{
|
||||||
public class HealthCheckMiddlewareTests
|
public class HealthCheckMiddlewareTests
|
||||||
{
|
{
|
||||||
[Theory]
|
[Fact] // Matches based on '.Map'
|
||||||
[InlineData("/frob")]
|
public async Task IgnoresRequestThatDoesNotMatchPath()
|
||||||
[InlineData("/health/")] // Match is exact, for now at least
|
|
||||||
public async Task IgnoresRequestThatDoesNotMatchPath(string requestPath)
|
|
||||||
{
|
{
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
|
|
@ -34,26 +32,190 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
var server = new TestServer(builder);
|
var server = new TestServer(builder);
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
|
|
||||||
var response = await client.GetAsync(requestPath);
|
var response = await client.GetAsync("/frob");
|
||||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Fact] // Matches based on '.Map'
|
||||||
[InlineData("/health")]
|
public async Task MatchIsCaseInsensitive()
|
||||||
[InlineData("/Health")]
|
{
|
||||||
[InlineData("/HEALTH")]
|
var builder = new WebHostBuilder()
|
||||||
public async Task ReturnsEmptyHealthyRequestIfNoHealthChecksRegistered(string requestPath)
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks();
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/HEALTH");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ReturnsPlainTextStatus()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks();
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StatusCodeIs200IfNoChecks()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks();
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StatusCodeIs200IfAllChecksHealthy()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StatusCodeIs200IfCheckIsDegraded()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Degraded("Not so great.")))
|
||||||
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Degraded", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StatusCodeIs503IfCheckIsUnhealthy()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Unhealthy("Pretty bad.")))
|
||||||
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Unhealthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StatusCodeIs500IfCheckIsFailed()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health");
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(new HealthCheckResult(HealthCheckStatus.Failed, null, null, null)))
|
||||||
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Failed", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DetailedJsonReturnsEmptyHealthyResponseIfNoHealthChecksRegistered()
|
||||||
{
|
{
|
||||||
var expectedJson = JsonConvert.SerializeObject(new
|
var expectedJson = JsonConvert.SerializeObject(new
|
||||||
{
|
{
|
||||||
status = "Healthy",
|
status = "Healthy",
|
||||||
results = new { }
|
results = new { }
|
||||||
}, Formatting.None);
|
}, Formatting.Indented);
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UseHealthChecks("/health");
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
ResponseWriter = HealthCheckResponseWriters.WriteDetailedJson,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
|
@ -62,14 +224,14 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
var server = new TestServer(builder);
|
var server = new TestServer(builder);
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
|
|
||||||
var response = await client.GetAsync(requestPath);
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
var result = await response.Content.ReadAsStringAsync();
|
var result = await response.Content.ReadAsStringAsync();
|
||||||
Assert.Equal(expectedJson, result);
|
Assert.Equal(expectedJson, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ReturnsResultsFromHealthChecks()
|
public async Task DetailedJsonReturnsResultsFromHealthChecks()
|
||||||
{
|
{
|
||||||
var expectedJson = JsonConvert.SerializeObject(new
|
var expectedJson = JsonConvert.SerializeObject(new
|
||||||
{
|
{
|
||||||
|
|
@ -101,12 +263,15 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
data = new { }
|
data = new { }
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, Formatting.None);
|
}, Formatting.Indented);
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UseHealthChecks("/health");
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
ResponseWriter = HealthCheckResponseWriters.WriteDetailedJson,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
|
@ -129,78 +294,15 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task StatusCodeIs200IfNoChecks()
|
public async Task NoResponseWriterReturnsEmptyBody()
|
||||||
{
|
{
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UseHealthChecks("/health");
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
})
|
{
|
||||||
.ConfigureServices(services =>
|
ResponseWriter = null,
|
||||||
{
|
});
|
||||||
services.AddHealthChecks();
|
|
||||||
});
|
|
||||||
var server = new TestServer(builder);
|
|
||||||
var client = server.CreateClient();
|
|
||||||
|
|
||||||
var response = await client.GetAsync("/health");
|
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task StatusCodeIs200IfAllChecksHealthy()
|
|
||||||
{
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHealthChecks("/health");
|
|
||||||
})
|
|
||||||
.ConfigureServices(services =>
|
|
||||||
{
|
|
||||||
services.AddHealthChecks()
|
|
||||||
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
|
||||||
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
|
||||||
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
|
||||||
});
|
|
||||||
var server = new TestServer(builder);
|
|
||||||
var client = server.CreateClient();
|
|
||||||
|
|
||||||
var response = await client.GetAsync("/health");
|
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task StatusCodeIs200IfCheckIsDegraded()
|
|
||||||
{
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHealthChecks("/health");
|
|
||||||
})
|
|
||||||
.ConfigureServices(services =>
|
|
||||||
{
|
|
||||||
services.AddHealthChecks()
|
|
||||||
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
|
||||||
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Degraded("Not so great.")))
|
|
||||||
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
|
||||||
});
|
|
||||||
var server = new TestServer(builder);
|
|
||||||
var client = server.CreateClient();
|
|
||||||
|
|
||||||
var response = await client.GetAsync("/health");
|
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task StatusCodeIs503IfCheckIsUnhealthy()
|
|
||||||
{
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHealthChecks("/health");
|
|
||||||
})
|
})
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
|
@ -215,21 +317,57 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
var response = await client.GetAsync("/health");
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
|
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
|
||||||
|
Assert.Equal(string.Empty, await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task StatusCodeIs500IfCheckIsFailed()
|
public async Task CanSetCustomStatusCodes()
|
||||||
{
|
{
|
||||||
var builder = new WebHostBuilder()
|
var builder = new WebHostBuilder()
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UseHealthChecks("/health");
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
ResultStatusCodes =
|
||||||
|
{
|
||||||
|
[HealthCheckStatus.Healthy] = 201,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks();
|
||||||
|
});
|
||||||
|
var server = new TestServer(builder);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanFilterChecks()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
HealthCheckNames =
|
||||||
|
{
|
||||||
|
"Baz",
|
||||||
|
"FOO",
|
||||||
|
},
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
services.AddHealthChecks()
|
services.AddHealthChecks()
|
||||||
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
.AddCheck("Bar", () => Task.FromResult(new HealthCheckResult(HealthCheckStatus.Failed, null, null, null)))
|
// Will get filtered out
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Unhealthy("A-ok!")))
|
||||||
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
});
|
});
|
||||||
var server = new TestServer(builder);
|
var server = new TestServer(builder);
|
||||||
|
|
@ -237,7 +375,38 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
|
|
||||||
var response = await client.GetAsync("/health");
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanFilterChecks_ThrowsForMissingCheck()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseHealthChecks("/health", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
HealthCheckNames =
|
||||||
|
{
|
||||||
|
"Bazzzzzz",
|
||||||
|
"FOO",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddHealthChecks()
|
||||||
|
.AddCheck("Foo", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")))
|
||||||
|
.AddCheck("Bar", () => Task.FromResult(HealthCheckResult.Unhealthy("A-ok!")))
|
||||||
|
.AddCheck("Baz", () => Task.FromResult(HealthCheckResult.Healthy("A-ok!")));
|
||||||
|
});
|
||||||
|
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(() => new TestServer(builder));
|
||||||
|
Assert.Equal(
|
||||||
|
"The following health checks were not found: 'Bazzzzzz'. Registered health checks: 'Foo, Bar, Baz'.",
|
||||||
|
ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\samples\HealthChecksSample\HealthChecksSample.csproj" />
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics.HealthChecks\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj" />
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Diagnostics.HealthChecks\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue