Garbage Collection Performance Monitor for .NET

public class GCPerformanceMonitor
{
    private readonly ILogger<GCPerformanceMonitor> _logger;
    private readonly Timer _monitoringTimer;
    private readonly Dictionary<string, double> _metrics = new();
    
    public GCPerformanceMonitor(ILogger<GCPerformanceMonitor> logger)
    {
        _logger = logger;
        _monitoringTimer = new Timer(CollectMetrics, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
    }
    
    private void CollectMetrics(object state)
    {
        var gcInfo = GC.GetTotalMemory(false);
        var gen0 = GC.CollectionCount(0);
        var gen1 = GC.CollectionCount(1);
        var gen2 = GC.CollectionCount(2);
        
        var previousGen0 = _metrics.GetValueOrDefault("gen0_collections", 0);
        var previousGen1 = _metrics.GetValueOrDefault("gen1_collections", 0);
        var previousGen2 = _metrics.GetValueOrDefault("gen2_collections", 0);
        
        var gen0Rate = gen0 - previousGen0;
        var gen1Rate = gen1 - previousGen1;
        var gen2Rate = gen2 - previousGen2;
        
        _metrics["gen0_collections"] = gen0;
        _metrics["gen1_collections"] = gen1;
        _metrics["gen2_collections"] = gen2;
        _metrics["total_memory"] = gcInfo;
        _metrics["gen0_rate"] = gen0Rate;
        _metrics["gen1_rate"] = gen1Rate;
        _metrics["gen2_rate"] = gen2Rate;
        
        // Alert on excessive Gen1/Gen2 collections
        if (gen1Rate > 10 || gen2Rate > 2)
        {
            _logger.LogWarning("High GC activity detected. Gen1: {Gen1Rate}/min, Gen2: {Gen2Rate}/min, Memory: {Memory:N0} bytes", 
                gen1Rate, gen2Rate, gcInfo);
        }
        
        // Log metrics for external monitoring systems
        _logger.LogInformation("GC Metrics: Gen0={Gen0Rate} Gen1={Gen1Rate} Gen2={Gen2Rate} Memory={Memory:N0}", 
            gen0Rate, gen1Rate, gen2Rate, gcInfo);
    }
    
    public void Dispose()
    {
        _monitoringTimer?.Dispose();
    }
}