Xabaril / AspNetCore.Diagnostics.HealthChecks

Enterprise HealthChecks for ASP.NET Core Diagnostics Package
Apache License 2.0
3.99k stars 778 forks source link

Relative paths for the health-check UI only appear to be working on local iis express or Kestrel #1420

Open DanielPollackDev opened 1 year ago

DanielPollackDev commented 1 year ago

Relative paths for the health-check UI only appear to be working on local iis express or Kestrel when run from Visual Studio. I am not able to get this to work correctly in a deployed environment. When deployed, the UI comes up, but displays an error message stating: Could not get endpoint uri from configuration. I am using .net6. My appsettings.json config section looks like this: "HealthChecksUI": { "HealthChecks": [ { "Name": "Configuration-Service", "Uri": "/healthz" } ], "Webhooks": [ { "Name": "", "Uri": "", "Payload": "", "RestoredPayload": "" } ] },

My program.cs file looks like this:

... builder.Services.AddHealthChecks() ... builder.Services.AddHealthChecksUI().AddInMemoryStorage(); ... app.MapHealthChecks("/healthz", new HealthCheckOptions { Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); ... app.UseHttpsRedirection(); app.MapHealthChecksUI(); app.UseRouting(); app.MapControllers(); app.Run();

Khaos66 commented 1 year ago

Had this issue as well. Here is my workaround:

Add package Microsoft.Web.Administration

public static class IisHelper
{
    public static string? GetIisUrl(IWebHostEnvironment env)
    {
        try
        {
            using ServerManager serverManager = new ServerManager();
            var site = serverManager.Sites.FirstOrDefault(s => s.Name == env.ApplicationName);
            if (site?.Bindings?.Count > 0)
            {
                var binding = site.Bindings.First();
                var host = binding.Host;
                if (string.IsNullOrWhiteSpace(host))
                {
                    if (binding.EndPoint.Address != IPAddress.Any)
                    {
                        host = binding.EndPoint.Address.ToString();
                    }
                    else
                    {
                        host = Environment.MachineName;
                    }
                }
                var url = $"{binding.Protocol}://{host}:{binding.EndPoint.Port}";
                Log.Information("IIS serving url: {Url}", url);
                return url;
            }
        }
        catch(Exception ex)
        {
            Log.Warning(ex, "Unable to load IIS Url");
        }
        return null;
    }
}

Call it like this:

// Health Checks
string? iisUrl = IisHelper.GetIisUrl(builder.Environment);
builder.Services
        .AddHealthChecksUI(setup => setup.AddHealthCheckEndpoint("SWSIdentity", (iisUrl ?? string.Empty) + "/healthz"))
        .AddInMemoryStorage()
        .Services
            .AddHealthChecks()
            // ...
darraghjones commented 1 year ago

I think this issue might be related https://github.com/aspnet/Hosting/issues/956

danmcmyler-lancs commented 2 weeks ago

After being inspired by @Khaos66 this worked for me..

 public static class ApplicationUrlHelper
 {
     public static string GetApplicationBaseUrl(IConfiguration configuration)
     {
         var options = configuration.GetSection("ApplicationUrl").Get<ApplicationUrlOptions>();

         if (string.IsNullOrEmpty(options?.BaseUrl))
         {
             // Fallback to environment variable if configuration is not set
             var aspNetCoreUrls = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
             if (!string.IsNullOrEmpty(aspNetCoreUrls))
             {
                 var urls = aspNetCoreUrls.Split(';');
                 return urls[0]; // Use the first URL
             }

             // If all else fails, use a default or log a warning
             Log.Warning("ApplicationUrlHelper: Defaulting to localhost:4200");
             return "http://localhost:4200";

         }

         return options.BaseUrl;
     }
 }

//Program.cs

builder.Services.Configure<ApplicationUrlOptions>(builder.Configuration.GetSection("ApplicationUrl"));

string baseUrl = ApplicationUrlHelper.GetApplicationBaseUrl(configuration);

 services.AddHealthChecksUI(setupSettings: setup =>
 {
     setup.AddHealthCheckEndpoint("All", $"{baseUrl}/health/all");
     setup.AddHealthCheckEndpoint("External API Status", $"{baseUrl}/health/ext-api-status");
 }).AddInMemoryStorage();

//Apsettings.json

  "ApplicationUrl": {
    "BaseUrl": "https://www.yoursite.com"
  },