-
-
Save ReubenBond/2881c9f519910ca4a378d148346e9114 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Diagnostics.HealthChecks; | |
using Orleans.Concurrency; | |
using Orleans.Configuration; | |
using Orleans.Hosting; | |
using Orleans.Runtime; | |
namespace MyNamespace | |
{ | |
class Program | |
{ | |
static async Task Main(string[] args) | |
{ | |
// Configure the silo host | |
var silo = new SiloHostBuilder() | |
// ... your silo config ... | |
.EnableDirectClient() | |
.Build(); | |
// Start the silo | |
await silo.StartAsync(); | |
var webHost = new WebHostBuilder() | |
.UseKestrel(options => options.ListenAnyIP(8880)) | |
.ConfigureServices( | |
services => | |
{ | |
// Respond to health check probes. | |
services.AddHealthChecks() | |
.AddCheck<SiloHealthCheck>("SiloHealth") | |
.AddCheck<GrainHealthCheck>("GrainHealth"); | |
// Add the required services from the silo. | |
services.AddSingleton(sp => silo.Services.GetRequiredService<IClusterClient>()); | |
services.AddTransient( | |
sp => silo.Services.GetRequiredService<IEnumerable<IHealthCheckParticipant>>()); | |
}) | |
.UseStartup<Startup>() | |
.Build(); | |
await webHost.StartAsync(); | |
await Task.Delay(-1); | |
} | |
public interface ILocalHealthCheckGrain : IGrainWithGuidKey | |
{ | |
Task Ping(); | |
} | |
[StatelessWorker] | |
[CollectionAgeLimit(Minutes = 2)] | |
public class LocalHealthCheckGrain : Grain, ILocalHealthCheckGrain | |
{ | |
public Task Ping() => Task.CompletedTask; | |
} | |
public class GrainHealthCheck : IHealthCheck | |
{ | |
private readonly IClusterClient client; | |
public GrainHealthCheck(IClusterClient client) | |
{ | |
this.client = client; | |
} | |
public async Task<HealthCheckResult> CheckHealthAsync( | |
HealthCheckContext context, | |
CancellationToken cancellationToken = new CancellationToken()) | |
{ | |
try | |
{ | |
var localGrain = this.client.GetGrain<ILocalHealthCheckGrain>(Guid.Empty); | |
await localGrain.Ping(); | |
} | |
catch (Exception exception) | |
{ | |
return HealthCheckResult.Unhealthy("Unable to ping local health check grain", exception); | |
} | |
return HealthCheckResult.Healthy(); | |
} | |
} | |
public class SiloHealthCheck : IHealthCheck | |
{ | |
private DateTime lastCheckTime; | |
private readonly IEnumerable<IHealthCheckParticipant> participants; | |
public SiloHealthCheck(IEnumerable<IHealthCheckParticipant> participants) | |
{ | |
this.participants = participants; | |
} | |
public Task<HealthCheckResult> CheckHealthAsync( | |
HealthCheckContext context, | |
CancellationToken cancellationToken = new CancellationToken()) | |
{ | |
var lastChecked = this.lastCheckTime; | |
this.lastCheckTime = DateTime.UtcNow; | |
foreach (var participant in this.participants) | |
{ | |
if (!participant.CheckHealth(lastChecked)) | |
{ | |
return Task.FromResult(HealthCheckResult.Degraded()); | |
} | |
} | |
return Task.FromResult(HealthCheckResult.Healthy()); | |
} | |
} | |
public class Startup | |
{ | |
public void Configure(IApplicationBuilder app) | |
{ | |
app.UseHealthChecks("/healthz"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment