using System.Diagnostics; using App.Metrics; using Catalogger.Backend.Cache; using Catalogger.Backend.Database; using Humanizer; using Microsoft.EntityFrameworkCore; using NodaTime.Extensions; namespace Catalogger.Backend.Services; public class MetricsCollectionService( ILogger logger, GuildCacheService guildCache, ChannelCacheService channelCache, UserCacheService userCache, IMetrics metrics, IServiceProvider services) : BackgroundService { private readonly ILogger _logger = logger.ForContext(); private async Task CollectMetricsAsync() { var stopwatch = new Stopwatch(); stopwatch.Start(); await using var scope = services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService(); var messageCount = await db.Messages.CountAsync(); metrics.Measure.Gauge.SetValue(CataloggerMetrics.GuildsCached, guildCache.Size); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ChannelsCached, channelCache.Size); metrics.Measure.Gauge.SetValue(CataloggerMetrics.UsersCached, userCache.Size); metrics.Measure.Gauge.SetValue(CataloggerMetrics.MessagesStored, messageCount); var process = Process.GetCurrentProcess(); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ProcessPhysicalMemory, process.WorkingSet64); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ProcessVirtualMemory, process.VirtualMemorySize64); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ProcessPrivateMemory, process.PrivateMemorySize64); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ProcessThreads, process.Threads.Count); metrics.Measure.Gauge.SetValue(CataloggerMetrics.ProcessHandles, process.HandleCount); stopwatch.Stop(); metrics.Measure.Timer.Time(CataloggerMetrics.MetricsCollectionTime, stopwatch.ElapsedMilliseconds); _logger.Information("Collected metrics in {Duration}", stopwatch.ElapsedDuration()); await Task.WhenAll(((IMetricsRoot)metrics).ReportRunner.RunAllAsync()); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var timer = new PeriodicTimer(1.Minutes()); while (await timer.WaitForNextTickAsync(stoppingToken)) { _logger.Debug("Collecting periodic metrics"); await CollectMetricsAsync(); _logger.Debug("Reported metrics to backend"); } } }