From cf53ef618adb13d791254bc85392d057d22d041a Mon Sep 17 00:00:00 2001 From: adrianwium <82496337+adrianwium@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:53:55 +0200 Subject: [PATCH] Set up basic and detailed health checks at /api/v3/health/ready and /api/v3/health/live (#715) * Set up basic and detailed health checks at /api/v3/health/ready and /api/v3/health/live Enable anonymous access to these endpoints to allow health monitoring by external systems without authentication Utilize default ASP.NET Core Health Checks behavior to return HTTP 200 for Healthy and HTTP 503 for Unhealthy or Degraded states, facilitating straightforward integration with load balancers and monitoring tools * Linting --- helm/yoma-api/templates/deployment.yaml | 4 +-- .../src/application/Yoma.Core.Api/Startup.cs | 28 +++++++++++++------ .../Startup.cs | 11 ++++++-- .../Yoma.Core.Infrastructure.Database.csproj | 1 + 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/helm/yoma-api/templates/deployment.yaml b/helm/yoma-api/templates/deployment.yaml index ba584f177..eca4f025e 100644 --- a/helm/yoma-api/templates/deployment.yaml +++ b/helm/yoma-api/templates/deployment.yaml @@ -62,13 +62,13 @@ spec: {{- if .Values.livenessProbe.enabled }} livenessProbe: httpGet: - path: /index.html + path: /api/v3/health/live port: {{ .Values.service.portName | default "http" }} {{- end }} {{- if .Values.readinessProbe.enabled }} readinessProbe: httpGet: - path: /index.html + path: /api/v3/health/ready port: {{ .Values.service.portName | default "http" }} {{- end }} resources: diff --git a/src/api/src/application/Yoma.Core.Api/Startup.cs b/src/api/src/application/Yoma.Core.Api/Startup.cs index f996688fc..91ab7abf6 100644 --- a/src/api/src/application/Yoma.Core.Api/Startup.cs +++ b/src/api/src/application/Yoma.Core.Api/Startup.cs @@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Converters; using StackExchange.Redis; @@ -81,6 +83,7 @@ public void ConfigureServices(IServiceCollection services) services.AddHttpContextAccessor(); services.AddMemoryCache(); + services.AddHealthChecks().AddCheck("API Ready Check", () => HealthCheckResult.Healthy("API is up"), tags: ["ready"]); #endregion #region 3rd Party @@ -128,24 +131,31 @@ public void Configure(IApplicationBuilder app) if (_appSettings.HttpsRedirectionEnabledEnvironmentsAsEnum.HasFlag(_environment)) app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => + { + // basic check to ensure the API is up + endpoints.MapHealthChecks("/api/v3/health/ready", new HealthCheckOptions + { + Predicate = (check) => check.Tags.Contains("ready") + }).AllowAnonymous(); + + // more detailed check to ensure the API can connect to the database + endpoints.MapHealthChecks("/api/v3/health/live", new HealthCheckOptions + { + Predicate = (check) => check.Tags.Contains("live") + }).AllowAnonymous(); + }); //enabling sentry tracing causes endless information logs about 'Sentry trace header is null' //if (_environment != Domain.Core.Environment.Local) app.UseSentryTracing(); - - app.UseAuthentication(); - app.UseAuthorization(); #endregion #region 3rd Party app.UseHangfireDashboard(options: new DashboardOptions { DarkModeEnabled = true, - /* - TODO: Resolve shared Data Protection Keys (NFS or S3 or SSM or Postgres) and set this back to `false` - * https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/implementation/key-storage-providers - * https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview - * https://github.com/aws/aws-ssm-data-protection-provider-for-aspnet - */ IgnoreAntiforgeryToken = true, //replicas >=2 will cause antiforgery token issues Authorization = [new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions { diff --git a/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Startup.cs b/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Startup.cs index 302ccbd45..c65d4a2be 100644 --- a/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Startup.cs +++ b/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Startup.cs @@ -52,10 +52,17 @@ public static void ConfigureServices_InfrastructureDatabase(this IServiceCollect maxRetryDelay: TimeSpan.FromSeconds(appSettings.DatabaseRetryPolicy.MaxRetryDelayInSeconds), errorCodesToAdd: null); }) - .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.MultipleCollectionIncludeWarning)); //didable warning related to not using AsSplitQuery() as per MS SQL implementation - //.UseLazyLoadingProxies(): without arguments is used to enable lazy loading. Simply not calling UseLazyLoadingProxies() ensure lazy loading is not enabled + //disable warning related to not using AsSplitQuery() as per MS SQL implementation + //.UseLazyLoadingProxies(): without arguments is used to enable lazy loading. Simply not calling UseLazyLoadingProxies() ensure lazy loading is not enabled + .ConfigureWarnings(warnings => warnings.Ignore(RelationalEventId.MultipleCollectionIncludeWarning)); + }, ServiceLifetime.Scoped, ServiceLifetime.Scoped); + services.AddHealthChecks().AddNpgSql( + connectionString: configuration.Configuration_ConnectionString(), + name: "Database Connectivity Check", + tags: ["live"]); + // //if (environment == Domain.Core.Environment.Local) // HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); diff --git a/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Yoma.Core.Infrastructure.Database.csproj b/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Yoma.Core.Infrastructure.Database.csproj index 39a3b6605..ae8e6b1fe 100644 --- a/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Yoma.Core.Infrastructure.Database.csproj +++ b/src/api/src/infrastructure/Yoma.Core.Infrastructure.Database/Yoma.Core.Infrastructure.Database.csproj @@ -7,6 +7,7 @@ + all