All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 4s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Build and Push Image (push) Successful in 7m58s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Successful in 1m39s
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (push) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 1s
134 lines
5.2 KiB
C#
134 lines
5.2 KiB
C#
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using System.Diagnostics;
|
|
|
|
namespace BCards.Web.HealthChecks;
|
|
|
|
public class ExternalServicesHealthCheck : IHealthCheck
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
private readonly ILogger<ExternalServicesHealthCheck> _logger;
|
|
|
|
public ExternalServicesHealthCheck(HttpClient httpClient, ILogger<ExternalServicesHealthCheck> logger)
|
|
{
|
|
_httpClient = httpClient;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<HealthCheckResult> CheckHealthAsync(
|
|
HealthCheckContext context,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var stopwatch = Stopwatch.StartNew();
|
|
var results = new Dictionary<string, object>();
|
|
var allHealthy = true;
|
|
var hasUnhealthy = false;
|
|
|
|
try
|
|
{
|
|
// Lista de serviços externos para verificar
|
|
var services = new Dictionary<string, string>
|
|
{
|
|
{ "google_oauth", "https://accounts.google.com" },
|
|
{ "microsoft_oauth", "https://login.microsoftonline.com" }
|
|
};
|
|
|
|
foreach (var service in services)
|
|
{
|
|
var serviceStopwatch = Stopwatch.StartNew();
|
|
try
|
|
{
|
|
using var response = await _httpClient.GetAsync(service.Value, cancellationToken);
|
|
serviceStopwatch.Stop();
|
|
|
|
var serviceResult = new Dictionary<string, object>
|
|
{
|
|
{ "status", response.IsSuccessStatusCode ? "healthy" : "unhealthy" },
|
|
{ "duration", $"{serviceStopwatch.ElapsedMilliseconds}ms" },
|
|
{ "status_code", (int)response.StatusCode },
|
|
{ "url", service.Value }
|
|
};
|
|
|
|
results[service.Key] = serviceResult;
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
allHealthy = false;
|
|
if (response.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable ||
|
|
response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
|
|
{
|
|
hasUnhealthy = true;
|
|
}
|
|
}
|
|
|
|
_logger.LogInformation("External service {Service} health check: {Status} in {Duration}ms",
|
|
service.Key, response.StatusCode, serviceStopwatch.ElapsedMilliseconds);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
serviceStopwatch.Stop();
|
|
allHealthy = false;
|
|
hasUnhealthy = true;
|
|
|
|
results[service.Key] = new Dictionary<string, object>
|
|
{
|
|
{ "status", "unhealthy" },
|
|
{ "duration", $"{serviceStopwatch.ElapsedMilliseconds}ms" },
|
|
{ "error", ex.Message },
|
|
{ "url", service.Value }
|
|
};
|
|
|
|
// Usar Warning para OAuth providers (alerta amarelo)
|
|
if (service.Key.Contains("oauth"))
|
|
{
|
|
_logger.LogWarning("🟡 OAuth service {Service} offline - usuários não conseguem fazer login: {Error}",
|
|
service.Key, ex.Message);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogError(ex, "🔴 Critical service {Service} failed", service.Key);
|
|
}
|
|
}
|
|
}
|
|
|
|
stopwatch.Stop();
|
|
var totalDuration = stopwatch.ElapsedMilliseconds;
|
|
|
|
var data = new Dictionary<string, object>
|
|
{
|
|
{ "status", hasUnhealthy ? "unhealthy" : (allHealthy ? "healthy" : "degraded") },
|
|
{ "duration", $"{totalDuration}ms" },
|
|
{ "services", results },
|
|
{ "total_services", services.Count },
|
|
{ "healthy_services", results.Values.Count(r => ((Dictionary<string, object>)r)["status"].ToString() == "healthy") }
|
|
};
|
|
|
|
if (hasUnhealthy)
|
|
{
|
|
return HealthCheckResult.Unhealthy("One or more external services are unhealthy", data: data);
|
|
}
|
|
|
|
if (!allHealthy)
|
|
{
|
|
return HealthCheckResult.Degraded("Some external services have issues", data: data);
|
|
}
|
|
|
|
return HealthCheckResult.Healthy($"All external services are responsive ({totalDuration}ms)", data: data);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
stopwatch.Stop();
|
|
var duration = stopwatch.ElapsedMilliseconds;
|
|
|
|
_logger.LogError(ex, "External services health check failed after {Duration}ms", duration);
|
|
|
|
var data = new Dictionary<string, object>
|
|
{
|
|
{ "status", "unhealthy" },
|
|
{ "duration", $"{duration}ms" },
|
|
{ "error", ex.Message }
|
|
};
|
|
|
|
return HealthCheckResult.Unhealthy($"External services check failed: {ex.Message}", ex, data);
|
|
}
|
|
}
|
|
} |