using Microsoft.Extensions.Diagnostics.HealthChecks; using System.Diagnostics; namespace BCards.Web.HealthChecks; public class ExternalServicesHealthCheck : IHealthCheck { private readonly HttpClient _httpClient; private readonly ILogger _logger; public ExternalServicesHealthCheck(HttpClient httpClient, ILogger logger) { _httpClient = httpClient; _logger = logger; } public async Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) { var stopwatch = Stopwatch.StartNew(); var results = new Dictionary(); var allHealthy = true; var hasUnhealthy = false; try { // Lista de serviços externos para verificar var services = new Dictionary { { "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 { { "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 { { "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 { { "status", hasUnhealthy ? "unhealthy" : (allHealthy ? "healthy" : "degraded") }, { "duration", $"{totalDuration}ms" }, { "services", results }, { "total_services", services.Count }, { "healthy_services", results.Values.Count(r => ((Dictionary)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 { { "status", "unhealthy" }, { "duration", $"{duration}ms" }, { "error", ex.Message } }; return HealthCheckResult.Unhealthy($"External services check failed: {ex.Message}", ex, data); } } }