0

I added health checks to my ASP.NET Core 6 app, and everything is working properly.

I need to determine (programmatically, at runtime) all the health check routes, e.g. /healthz, etc.

I tried:

// inject IEnumerable<EndpointDataSource>
// ...
var routes = _endpointDataSources.SelectMany(source => source.Endpoints);

But there's no way I can select the correct endpoints (using linq) without using a hack or magic string. The healthcheck endpoints have "Heath checks" as their display names, but I assume that can change at any time, so it's not reliable.

How can I get those endpoints in a reliable way that won't break on the next update?

lonix
  • 14,255
  • 23
  • 85
  • 176
  • check this: https://stackoverflow.com/questions/28435734/how-to-get-a-list-of-all-routes-in-asp-net-core. shows how to iterate all your endpoints. – bmiller Jul 20 '22 at 02:42
  • @bmiller Thanks! I tried something similar (updated the question accordingly), but it's not a reliable way as the healthcheck endpoints have no property I can use to select them in a linq query (without using magic strings). – lonix Jul 20 '22 at 03:03
  • can you add the part where are you adding healthcheck to your application. – CodingMytra Jul 20 '22 at 04:02

1 Answers1

1

Health checks are (currently) implemented by creating a middleware pipeline and mapping the resulting delegate, with a display name "Health checks".

var pipeline = endpoints.CreateApplicationBuilder()
    .UseMiddleware<HealthCheckMiddleware>(args)
    .Build();

return endpoints.Map(pattern, pipeline)
    .WithDisplayName(DefaultDisplayName);

As you have discovered, you should be able to discover all endpoints, search for any health checks, and list their path via;

var sources = provider.GetService<IEnumerable<EndpointDataSource>>(); // via DI

var routes = sources
    .SelectMany(s => s.Endpoints)
    .OfType<RouteEndpoint>()
    .Where(e => e.DisplayName == "Health checks")
    .Select(e => e.RoutePattern)
    .ToList();

So to answer your actual question, while the method you would use to configure endpoint routes is unlikely to change. There are mentions in the documentation demonstrating how endpoint routing meta data can be examined. But I wouldn't expect any strong guarantee of future support.

Jeremy Lakeman
  • 9,515
  • 25
  • 29
  • Thanks. Looks like the magic string is [set here](https://github.com/dotnet/aspnetcore/blob/0602a3266ea9d116df479d558cd99e854d4bc03d/src/Middleware/HealthChecks/src/Builder/HealthCheckEndpointRouteBuilderExtensions.cs#L18). I don't know how reliable it is, but looks like there's no other way. – lonix Jul 20 '22 at 06:38
  • I would add this: `.Where(x => e.RequestDelegate?.Target is HealthCheckMiddleware || e.DisplayName == "Health checks")`. Seems safer than relying on that string alone. – lonix Jul 20 '22 at 06:38
  • Checking just the target is probably better. Assuming that part of pipeline request delegates always works that way.... – Jeremy Lakeman Jul 20 '22 at 06:45
  • True, even that could change! The issue with these sort of problems is the plumbing is hidden once the app is built. Not much is exposed at that point. – lonix Jul 20 '22 at 06:46