From a7ec744fe20c5bb177d7cea338c9f5c9c16256b6 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Thu, 5 Dec 2024 18:08:52 +0700 Subject: [PATCH] Health Checks for Background --- README.md | 23 ++--- .../ClassifiedAds.Background/Program.cs | 10 +++ .../HealthChecksBackgroundService.cs | 84 +++++++++++++++++++ .../ConfigurationOptions/AppSettings.cs | 3 - src/Monolith/ClassifiedAds.WebMVC/Program.cs | 10 +-- .../ClassifiedAds.WebMVC/appsettings.json | 54 ------------ src/Monolith/docker-compose.yml | 8 -- 7 files changed, 102 insertions(+), 90 deletions(-) create mode 100644 src/Monolith/ClassifiedAds.Infrastructure/HostedServices/HealthChecksBackgroundService.cs diff --git a/README.md b/README.md index 2df6b9c5f..983e110f6 100644 --- a/README.md +++ b/README.md @@ -169,10 +169,7 @@ Message Broker - Open below files and jump to **MessageBroker** section: - + [ClassifiedAds.IdentityServer/appsettings.json](/src/Monolith/ClassifiedAds.IdentityServer/appsettings.json) - + [ClassifiedAds.WebMVC/appsettings.json](/src/Monolith/ClassifiedAds.WebMVC/appsettings.json) - + [ClassifiedAds.WebAPI/appsettings.json](/src/Monolith/ClassifiedAds.WebAPI/appsettings.json) - + [ClassifiedAds.BackgroundServer/appsettings.json](/src/Monolith/ClassifiedAds.BackgroundServer/appsettings.json) + + [ClassifiedAds.Background/appsettings.json](/src/Monolith/ClassifiedAds.Background/appsettings.json) ```js "MessageBroker": { "Provider": "RabbitMQ", @@ -299,8 +296,7 @@ - Open and jump to **Logging** section of below files: + [ClassifiedAds.WebAPI/appsettings.json](/src/Monolith/ClassifiedAds.WebAPI/appsettings.json) + [ClassifiedAds.WebMVC/appsettings.json](/src/Monolith/ClassifiedAds.WebMVC/appsettings.json) - + [ClassifiedAds.IdentityServer/appsettings.json](/src/Monolith/ClassifiedAds.IdentityServer/appsettings.json) - + [ClassifiedAds.BackgroundServer/appsettings.json](/src/Monolith/ClassifiedAds.BackgroundServer/appsettings.json) + + [ClassifiedAds.Background/appsettings.json](/src/Monolith/ClassifiedAds.Background/appsettings.json) ```js "Logging": { "LogLevel": { @@ -381,7 +377,6 @@ - Open and jump to **Caching** section of below files: + [ClassifiedAds.WebAPI/appsettings.json](/src/Monolith/ClassifiedAds.WebAPI/appsettings.json) + [ClassifiedAds.WebMVC/appsettings.json](/src/Monolith/ClassifiedAds.WebMVC/appsettings.json) - + [ClassifiedAds.IdentityServer/appsettings.json](/src/Monolith/ClassifiedAds.IdentityServer/appsettings.json) ```js "Caching": { "InMemory": { @@ -448,7 +443,6 @@ - Open and jump to **Monitoring** section of below files: + [ClassifiedAds.WebAPI/appsettings.json](/src/Monolith/ClassifiedAds.WebAPI/appsettings.json) + [ClassifiedAds.WebMVC/appsettings.json](/src/Monolith/ClassifiedAds.WebMVC/appsettings.json) - + [ClassifiedAds.IdentityServer/appsettings.json](/src/Monolith/ClassifiedAds.IdentityServer/appsettings.json) ```js "Monitoring": { "MiniProfiler": { @@ -555,8 +549,7 @@ - Open and jump to **Interceptors** section of below files: + [ClassifiedAds.WebAPI/appsettings.json](/src/Monolith/ClassifiedAds.WebAPI/appsettings.json) + [ClassifiedAds.WebMVC/appsettings.json](/src/Monolith/ClassifiedAds.WebMVC/appsettings.json) - + [ClassifiedAds.IdentityServer/appsettings.json](/src/Monolith/ClassifiedAds.IdentityServer/appsettings.json) - + [ClassifiedAds.BackgroundServer/appsettings.json](/src/Monolith/ClassifiedAds.BackgroundServer/appsettings.json) + + [ClassifiedAds.Background/appsettings.json](/src/Monolith/ClassifiedAds.Background/appsettings.json) ```js "Interceptors": { "LoggingInterceptor": true, @@ -602,12 +595,6 @@ "AllowedOrigins": [ "http://localhost:4200", "http://localhost:3000", "http://localhost:8080" ] }, ``` - - Open [ClassifiedAds.NotificationServer/appsettings.json](/src/Monolith/ClassifiedAds.NotificationServer/appsettings.json) and jump to **CORS** section: - ```js - "CORS": { - "AllowedOrigins": [ "https://localhost:44364", "http://host.docker.internal:9003" ] - } - ```
@@ -644,7 +631,7 @@
Sending Email - - Open [ClassifiedAds.BackgroundServer/appsettings.json](/src/Monolith/ClassifiedAds.BackgroundServer/appsettings.json) and jump to **Notification -> Email** section: + - Open [ClassifiedAds.Background/appsettings.json](/src/Monolith/ClassifiedAds.Background/appsettings.json) and jump to **Notification -> Email** section: ```js "Notification": { "Email": { @@ -672,7 +659,7 @@
Sending SMS - - Open [ClassifiedAds.BackgroundServer/appsettings.json](/src/Monolith/ClassifiedAds.BackgroundServer/appsettings.json) and jump to **Notification -> Sms** section: + - Open [ClassifiedAds.Background/appsettings.json](/src/Monolith/ClassifiedAds.Background/appsettings.json) and jump to **Notification -> Sms** section: ```js "Notification": { "Sms": { diff --git a/src/Monolith/ClassifiedAds.Background/Program.cs b/src/Monolith/ClassifiedAds.Background/Program.cs index 7f455944e..4b87699ac 100644 --- a/src/Monolith/ClassifiedAds.Background/Program.cs +++ b/src/Monolith/ClassifiedAds.Background/Program.cs @@ -13,6 +13,7 @@ using ClassifiedAds.Infrastructure.Logging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; using System.Reflection; @@ -70,6 +71,13 @@ services.AddSingleton(new AzureActiveDirectoryB2CIdentityProvider(appSettings.IdentityProviders.AzureActiveDirectoryB2C)); } + services.AddHealthChecks() + .AddSqlServer(connectionString: appSettings.ConnectionStrings.ClassifiedAds, + healthQuery: "SELECT 1;", + name: "Sql Server", + failureStatus: HealthStatus.Degraded) + .AddMessageBusHealthCheck(appSettings.MessageBroker); + services.AddHostedService>(); services.AddHostedService>(); services.AddHostedService(); @@ -77,6 +85,8 @@ services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); + services.AddHostedService(); + }) .Build() .Run(); diff --git a/src/Monolith/ClassifiedAds.Infrastructure/HostedServices/HealthChecksBackgroundService.cs b/src/Monolith/ClassifiedAds.Infrastructure/HostedServices/HealthChecksBackgroundService.cs new file mode 100644 index 000000000..c87849ac2 --- /dev/null +++ b/src/Monolith/ClassifiedAds.Infrastructure/HostedServices/HealthChecksBackgroundService.cs @@ -0,0 +1,84 @@ +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace ClassifiedAds.Infrastructure.HostedServices; + +public class HealthChecksBackgroundService : BackgroundService +{ + private readonly IServiceProvider _services; + private readonly ILogger _logger; + private readonly HealthCheckService _healthCheckService; + + public HealthChecksBackgroundService(IServiceProvider services, + ILogger logger, + HealthCheckService healthCheckService) + { + _services = services; + _logger = logger; + _healthCheckService = healthCheckService; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + var jsonOptions = new JsonWriterOptions { Indented = true }; + + while (!stoppingToken.IsCancellationRequested) + { + var healthReport = await _healthCheckService.CheckHealthAsync(stoppingToken); + + using var memoryStream = new MemoryStream(); + using (var jsonWriter = new Utf8JsonWriter(memoryStream, jsonOptions)) + { + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("status", healthReport.Status.ToString()); + jsonWriter.WriteStartObject("results"); + + foreach (var healthReportEntry in healthReport.Entries) + { + jsonWriter.WriteStartObject(healthReportEntry.Key); + jsonWriter.WriteString("status", healthReportEntry.Value.Status.ToString()); + jsonWriter.WriteString("description", healthReportEntry.Value.Description ?? healthReportEntry.Value.Exception?.Message.ToString()); + jsonWriter.WriteStartObject("data"); + + foreach (var item in healthReportEntry.Value.Data) + { + jsonWriter.WritePropertyName(item.Key); + + JsonSerializer.Serialize(jsonWriter, item.Value, item.Value?.GetType() ?? typeof(object)); + } + + jsonWriter.WriteEndObject(); + + jsonWriter.WriteEndObject(); + } + + jsonWriter.WriteEndObject(); + jsonWriter.WriteEndObject(); + } + + var json = Encoding.UTF8.GetString(memoryStream.ToArray()); + + if (healthReport.Status == HealthStatus.Healthy) + { + _logger.LogInformation(json); + } + else if (healthReport.Status == HealthStatus.Degraded) + { + _logger.LogWarning(json); + } + else + { + _logger.LogError(json); + } + + await Task.Delay(60_000, stoppingToken); + } + } +} diff --git a/src/Monolith/ClassifiedAds.WebMVC/ConfigurationOptions/AppSettings.cs b/src/Monolith/ClassifiedAds.WebMVC/ConfigurationOptions/AppSettings.cs index e8440384f..97d56e6a6 100644 --- a/src/Monolith/ClassifiedAds.WebMVC/ConfigurationOptions/AppSettings.cs +++ b/src/Monolith/ClassifiedAds.WebMVC/ConfigurationOptions/AppSettings.cs @@ -2,7 +2,6 @@ using ClassifiedAds.Infrastructure.Configuration; using ClassifiedAds.Infrastructure.Interceptors; using ClassifiedAds.Infrastructure.Logging; -using ClassifiedAds.Infrastructure.MessageBrokers; using ClassifiedAds.Infrastructure.Monitoring; using ClassifiedAds.Infrastructure.Storages; using Microsoft.Extensions.Options; @@ -34,8 +33,6 @@ public class AppSettings public StorageOptions Storage { get; set; } - public MessageBrokerOptions MessageBroker { get; set; } - public CookiePolicyOptions CookiePolicyOptions { get; set; } public Dictionary SecurityHeaders { get; set; } diff --git a/src/Monolith/ClassifiedAds.WebMVC/Program.cs b/src/Monolith/ClassifiedAds.WebMVC/Program.cs index 83da09aff..b5abfca4f 100644 --- a/src/Monolith/ClassifiedAds.WebMVC/Program.cs +++ b/src/Monolith/ClassifiedAds.WebMVC/Program.cs @@ -1,5 +1,4 @@ -using ClassifiedAds.Application.FileEntries.DTOs; -using ClassifiedAds.CrossCuttingConcerns.Exceptions; +using ClassifiedAds.CrossCuttingConcerns.Exceptions; using ClassifiedAds.Domain.Identity; using ClassifiedAds.Infrastructure.Configuration; using ClassifiedAds.Infrastructure.HealthChecks; @@ -139,7 +138,7 @@ services.AddCaches(appSettings.Caching); -var healthChecksBuilder = services.AddHealthChecks() +services.AddHealthChecks() .AddSqlServer(connectionString: appSettings.ConnectionStrings.ClassifiedAds, healthQuery: "SELECT 1;", name: "Sql Server", @@ -150,8 +149,7 @@ .AddHttp(appSettings.ResourceServer.Endpoint, name: "Resource (Web API) Server", failureStatus: HealthStatus.Degraded) - .AddStorageManagerHealthCheck(appSettings.Storage) - .AddMessageBusHealthCheck(appSettings.MessageBroker); + .AddStorageManagerHealthCheck(appSettings.Storage); services.AddHealthChecksUI(setupSettings: setup => { @@ -163,8 +161,6 @@ services.AddScoped(); services.AddStorageManager(appSettings.Storage); -services.AddMessageBusSender(appSettings.MessageBroker); -services.AddMessageBusSender(appSettings.MessageBroker); services.AddFeatureManagement(); diff --git a/src/Monolith/ClassifiedAds.WebMVC/appsettings.json b/src/Monolith/ClassifiedAds.WebMVC/appsettings.json index a2f9024ff..45eff43a4 100644 --- a/src/Monolith/ClassifiedAds.WebMVC/appsettings.json +++ b/src/Monolith/ClassifiedAds.WebMVC/appsettings.json @@ -137,60 +137,6 @@ "RegionEndpoint": "ap-southeast-1" } }, - "MessageBroker": { - "Provider": "Fake", - "RabbitMQ": { - "HostName": "localhost", - "UserName": "guest", - "Password": "guest", - "ExchangeName": "amq.direct", - "RoutingKeys": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - }, - "QueueNames": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - } - }, - "Kafka": { - "BootstrapServers": "localhost:9092", - "Topics": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - }, - "GroupId": "classified" - }, - "AzureQueue": { - "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=xxx;EndpointSuffix=core.windows.net", - "QueueNames": { - "FileUploadedEvent": "classifiedadds-fileuploaded", - "FileDeletedEvent": "classifiedadds-filedeleted" - } - }, - "AzureServiceBus": { - "ConnectionString": "Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=xxx;SharedAccessKey=xxx", - "QueueNames": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - } - }, - "AzureEventGrid": { - "DomainEndpoint": "https://xxx.xxx-1.eventgrid.azure.net/api/events", - "DomainKey": "xxxx", - "Topics": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - } - }, - "AzureEventHub": { - "ConnectionString": "Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=xxx;SharedAccessKey=xxx", - "Hubs": { - "FileUploadedEvent": "classifiedadds_fileuploaded", - "FileDeletedEvent": "classifiedadds_filedeleted" - } - } - }, "CookiePolicyOptions": { }, diff --git a/src/Monolith/docker-compose.yml b/src/Monolith/docker-compose.yml index 5f4fb1de4..06e882c1d 100644 --- a/src/Monolith/docker-compose.yml +++ b/src/Monolith/docker-compose.yml @@ -90,10 +90,6 @@ services: Storage__Amazon__SecretAccessKey: ${Storage__Amazon__SecretAccessKey} Storage__Amazon__BucketName: ${Storage__Amazon__BucketName} Storage__Amazon__RegionEndpoint: ${Storage__Amazon__RegionEndpoint} - MessageBroker__Provider: ${MessageBroker__Provider} - MessageBroker__RabbitMQ__HostName: ${MessageBroker__RabbitMQ__HostName} - MessageBroker__Kafka__BootstrapServers: ${MessageBroker__Kafka__BootstrapServers} - MessageBroker__AzureQueue__ConnectionString: ${MessageBroker__AzureQueue__ConnectionString} webmvc: image: classifiedads.webmvc build: @@ -129,10 +125,6 @@ services: Storage__Amazon__SecretAccessKey: ${Storage__Amazon__SecretAccessKey} Storage__Amazon__BucketName: ${Storage__Amazon__BucketName} Storage__Amazon__RegionEndpoint: ${Storage__Amazon__RegionEndpoint} - MessageBroker__Provider: ${MessageBroker__Provider} - MessageBroker__RabbitMQ__HostName: ${MessageBroker__RabbitMQ__HostName} - MessageBroker__Kafka__BootstrapServers: ${MessageBroker__Kafka__BootstrapServers} - MessageBroker__AzureQueue__ConnectionString: ${MessageBroker__AzureQueue__ConnectionString} blazor: image: classifiedads.blazor build: