Updating Health Checks for 2.2
A bunch of small changes and updates for 2.2 focused at making our main scenarios more streamlined and focused. Also adds samples for extensibility we support so far. A list of changes: Clearing baselines for these projects. We didn't ship anything in 2.1 so there should be nothing in the baselines. -- The middleware now uses Map for path matching. This makes the actual `HealthCheckMiddleware` more standalone. This will make it easy to use with Dispatcher/Endpoint Routing in the future. This also manifests by removing Path from HealthCheckOptions - the path is an explicit argument to the UseHealthChecks middelware - this streamlines the design for 3.0. -- Added extensibility for customizing the status codes (aspnet/Home#2584) -- Added extensibility for writing the textual output (aspnet/Home#2583) -- Changed the default output to be `text/plain`. The most common use cases for health checks don't include a detailed status. The existing output format is still available as an option.
This commit is contained in:
parent
bf839dadf1
commit
47f427d5ac
|
|
@ -16,6 +16,7 @@
|
||||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>2.2.0-preview1-34823</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||||
|
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34823</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34823</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)" />
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,54 @@
|
||||||
|
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) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,10 @@
|
||||||
// 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.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
|
||||||
{
|
{
|
||||||
|
|
@ -19,60 +15,62 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
private readonly HealthCheckOptions _healthCheckOptions;
|
private readonly HealthCheckOptions _healthCheckOptions;
|
||||||
private readonly IHealthCheckService _healthCheckService;
|
private readonly IHealthCheckService _healthCheckService;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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
|
|
||||||
switch (result.Status)
|
|
||||||
{
|
|
||||||
case HealthCheckStatus.Failed:
|
|
||||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
||||||
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
|
|
||||||
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
|
|
||||||
|
// Get results
|
||||||
|
var result = await _healthCheckService.CheckHealthAsync(httpContext.RequestAborted);
|
||||||
|
|
||||||
|
// Map status to response code - this is customizable via options.
|
||||||
|
if (!_healthCheckOptions.ResultStatusCodes.TryGetValue(result.Status, out var statusCode))
|
||||||
{
|
{
|
||||||
await _next(context);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
@ -10,9 +14,23 @@ namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HealthCheckOptions
|
public class HealthCheckOptions
|
||||||
{
|
{
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the path at which the Health Check results will be available.
|
/// Gets or sets a delegate used to write the response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PathString Path { get; set; }
|
/// <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,62 @@
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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,29 +317,34 @@ 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 =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
services.AddHealthChecks()
|
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 server = new TestServer(builder);
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
|
|
||||||
var response = await client.GetAsync("/health");
|
var response = await client.GetAsync("/health");
|
||||||
|
|
||||||
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
|
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
|
||||||
|
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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