From 3236edd2bb66347cb032ba5b7989f8cd2bd17012 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Wed, 19 Nov 2025 00:59:49 +0700 Subject: [PATCH] Add Kaigen API health check and configuration - Introduced Kaigen configuration section in appsettings.Oda.json with BaseUrl. - Added HTTP client for Kaigen API health check in Program.cs. - Registered KaigenHealthCheck service for monitoring Kaigen API connectivity. --- .../HealthChecks/KaigenHealthCheck.cs | 94 +++++++++++++++++++ src/Managing.Api/Program.cs | 10 ++ src/Managing.Api/appsettings.Oda.json | 3 + 3 files changed, 107 insertions(+) create mode 100644 src/Managing.Api/HealthChecks/KaigenHealthCheck.cs diff --git a/src/Managing.Api/HealthChecks/KaigenHealthCheck.cs b/src/Managing.Api/HealthChecks/KaigenHealthCheck.cs new file mode 100644 index 00000000..91b80a15 --- /dev/null +++ b/src/Managing.Api/HealthChecks/KaigenHealthCheck.cs @@ -0,0 +1,94 @@ +using System.Text.Json; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Managing.Api.HealthChecks +{ + public class KaigenHealthCheck : IHealthCheck + { + private readonly HttpClient _httpClient; + private readonly string _kaigenBaseUrl; + + public KaigenHealthCheck(IHttpClientFactory httpClientFactory, string kaigenBaseUrl) + { + _httpClient = httpClientFactory.CreateClient("KaigenHealthCheck"); + _kaigenBaseUrl = kaigenBaseUrl; + } + + public async Task CheckHealthAsync(HealthCheckContext context, + CancellationToken cancellationToken = default) + { + try + { + var response = await _httpClient.GetAsync($"{_kaigenBaseUrl}/api/health", cancellationToken); + + if (!response.IsSuccessStatusCode) + { + return HealthCheckResult.Degraded( + $"Kaigen API health check failed with status code: {response.StatusCode}", + data: new Dictionary + { + ["StatusCode"] = (int)response.StatusCode, + ["Endpoint"] = $"{_kaigenBaseUrl}/api/health" + }); + } + + var content = await response.Content.ReadAsStringAsync(cancellationToken); + + // Parse the JSON response to extract the detailed data + using (JsonDocument document = JsonDocument.Parse(content)) + { + var root = document.RootElement; + string status = "OK"; + string message = "Server is healthy"; + + if (root.TryGetProperty("status", out var statusElement)) + { + status = statusElement.GetString(); + } + + if (root.TryGetProperty("message", out var messageElement)) + { + message = messageElement.GetString(); + } + + // Extract the detailed data from the Kaigen response + var data = new Dictionary(); + + // Parse timestamp if available + if (root.TryGetProperty("timestamp", out var timestampElement)) + { + data["timestamp"] = timestampElement.GetString(); + } + + data["message"] = message; + + // Determine overall health result based on status + if (status.ToUpper() == "OK") + { + return HealthCheckResult.Healthy( + "Kaigen API is healthy", + data: data); + } + else + { + return HealthCheckResult.Unhealthy( + $"Kaigen API returned status: {status}", + data: data); + } + } + } + catch (Exception ex) + { + return HealthCheckResult.Unhealthy( + "Failed to connect to Kaigen API", + ex, + data: new Dictionary + { + ["Endpoint"] = $"{_kaigenBaseUrl}/api/health", + ["ErrorMessage"] = ex.Message, + ["ErrorType"] = ex.GetType().Name + }); + } + } + } +} diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index 376ed5e2..9852425f 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -78,11 +78,16 @@ builder.Services.AddHealthChecks() var postgreSqlConnectionString = builder.Configuration.GetSection(Constants.Databases.PostgreSql)["ConnectionString"]; var influxUrl = builder.Configuration.GetSection(Constants.Databases.InfluxDb)["Url"]; var web3ProxyUrl = builder.Configuration.GetSection("Web3Proxy")["BaseUrl"]; +var kaigenBaseUrl = builder.Configuration.GetSection("Kaigen")["BaseUrl"]; // Add HTTP client for Web3Proxy health check with detailed response builder.Services.AddHttpClient("Web3ProxyHealthCheck") .ConfigureHttpClient(client => { client.Timeout = TimeSpan.FromSeconds(15); }); +// Add HTTP client for Kaigen API health check +builder.Services.AddHttpClient("KaigenHealthCheck") + .ConfigureHttpClient(client => { client.Timeout = TimeSpan.FromSeconds(15); }); + // Add HTTP client for GMX API health check builder.Services.AddHttpClient("GmxHealthCheck") .ConfigureHttpClient(client => { client.Timeout = TimeSpan.FromSeconds(10); }); @@ -91,6 +96,10 @@ builder.Services.AddHttpClient("GmxHealthCheck") builder.Services.AddSingleton(sp => new Web3ProxyHealthCheck(sp.GetRequiredService(), web3ProxyUrl)); +// Register KaigenHealthCheck with the kaigenBaseUrl +builder.Services.AddSingleton(sp => + new KaigenHealthCheck(sp.GetRequiredService(), kaigenBaseUrl)); + // Add SQL Loop Detection Service with Sentry integration // Configure SQL monitoring settings builder.Services.Configure(builder.Configuration.GetSection("SqlMonitoring")); @@ -149,6 +158,7 @@ builder.Services.AddHealthChecks() .AddCheck("candle-data", tags: ["database", "candles"]) .AddCheck("candle-data-detailed", tags: ["database", "candles-detailed"]) .AddCheck("gmx-connectivity", tags: ["api", "external"]) + .AddCheck("kaigen-api", tags: ["api", "external"]) .AddCheck("orleans-cluster", tags: ["orleans", "cluster"]); builder.Host.UseSerilog((hostBuilder, loggerConfiguration) => diff --git a/src/Managing.Api/appsettings.Oda.json b/src/Managing.Api/appsettings.Oda.json index 828fe3cc..3ef9bdda 100644 --- a/src/Managing.Api/appsettings.Oda.json +++ b/src/Managing.Api/appsettings.Oda.json @@ -12,6 +12,9 @@ "AppId": "cm6f47n1l003jx7mjwaembhup", "AppSecret": "63Chz2z5M8TgR5qc8dznSLRAGTHTyPU4cjdQobrBF1Cx5tszZpTuFgyrRd7hZ2k6HpwDz3GEwQZzsCqHb8Z311bF" }, + "Kaigen": { + "BaseUrl": "https://kaigen-back.apps.managing.live" + }, "Serilog": { "MinimumLevel": { "Default": "Information",