using Microsoft.Extensions.Diagnostics.HealthChecks; using System.Diagnostics; namespace BCards.Web.HealthChecks; public class SystemResourcesHealthCheck : IHealthCheck { private readonly ILogger _logger; private static readonly DateTime _startTime = DateTime.UtcNow; public SystemResourcesHealthCheck(ILogger logger) { _logger = logger; } public Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) { var stopwatch = Stopwatch.StartNew(); try { // Informações de memória var totalMemory = GC.GetTotalMemory(false); var workingSet = Environment.WorkingSet; // Informações do processo atual using var currentProcess = Process.GetCurrentProcess(); var cpuUsage = GetCpuUsage(currentProcess); // Uptime var uptime = DateTime.UtcNow - _startTime; var uptimeString = FormatUptime(uptime); // Thread count var threadCount = currentProcess.Threads.Count; stopwatch.Stop(); var duration = stopwatch.ElapsedMilliseconds; var data = new Dictionary { { "status", "healthy" }, { "duration", $"{duration}ms" }, { "memory", new Dictionary { { "total_managed_mb", Math.Round(totalMemory / 1024.0 / 1024.0, 2) }, { "working_set_mb", Math.Round(workingSet / 1024.0 / 1024.0, 2) }, { "gc_generation_0", GC.CollectionCount(0) }, { "gc_generation_1", GC.CollectionCount(1) }, { "gc_generation_2", GC.CollectionCount(2) } } }, { "process", new Dictionary { { "id", currentProcess.Id }, { "threads", threadCount }, { "handles", currentProcess.HandleCount }, { "uptime", uptimeString }, { "uptime_seconds", (int)uptime.TotalSeconds } } }, { "system", new Dictionary { { "processor_count", Environment.ProcessorCount }, { "os_version", Environment.OSVersion.ToString() }, { "machine_name", Environment.MachineName }, { "user_name", Environment.UserName } } } }; _logger.LogInformation("System resources health check completed in {Duration}ms - Memory: {Memory}MB, Threads: {Threads}", duration, Math.Round(totalMemory / 1024.0 / 1024.0, 1), threadCount); // Definir thresholds para status var memoryMb = totalMemory / 1024.0 / 1024.0; if (memoryMb > 1000) // > 1GB { data["status"] = "degraded"; return Task.FromResult(HealthCheckResult.Degraded($"High memory usage: {memoryMb:F1}MB", data: data)); } if (threadCount > 500) { data["status"] = "degraded"; return Task.FromResult(HealthCheckResult.Degraded($"High thread count: {threadCount}", data: data)); } return Task.FromResult(HealthCheckResult.Healthy($"System resources normal (Memory: {memoryMb:F1}MB, Threads: {threadCount})", data: data)); } catch (Exception ex) { stopwatch.Stop(); var duration = stopwatch.ElapsedMilliseconds; _logger.LogError(ex, "System resources health check failed after {Duration}ms", duration); var data = new Dictionary { { "status", "unhealthy" }, { "duration", $"{duration}ms" }, { "error", ex.Message } }; return Task.FromResult(HealthCheckResult.Unhealthy($"System resources check failed: {ex.Message}", ex, data)); } } private static double GetCpuUsage(Process process) { try { return process.TotalProcessorTime.TotalMilliseconds; } catch { return 0; } } private static string FormatUptime(TimeSpan uptime) { if (uptime.TotalDays >= 1) return $"{(int)uptime.TotalDays}d {uptime.Hours}h {uptime.Minutes}m"; if (uptime.TotalHours >= 1) return $"{uptime.Hours}h {uptime.Minutes}m"; if (uptime.TotalMinutes >= 1) return $"{uptime.Minutes}m {uptime.Seconds}s"; return $"{uptime.Seconds}s"; } }