// Copyright (C) 2021-present sam (starshines.gay) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using System.Diagnostics; using Catalogger.Backend.Cache.InMemoryCache; using Catalogger.Backend.Database; using Humanizer; using Microsoft.EntityFrameworkCore; using Prometheus; namespace Catalogger.Backend.Services; public class MetricsCollectionService( ILogger logger, GuildCache guildCache, ChannelCache channelCache, UserCache userCache, IServiceProvider services ) { private readonly ILogger _logger = logger.ForContext(); public async Task CollectMetricsAsync(CancellationToken ct = default) { var timer = CataloggerMetrics.MetricsCollectionTime.NewTimer(); await using var scope = services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService(); var messageCount = await db.Messages.CountAsync(ct); CataloggerMetrics.GuildsCached.Set(guildCache.Size); CataloggerMetrics.ChannelsCached.Set(channelCache.Size); CataloggerMetrics.UsersCached.Set(userCache.Size); CataloggerMetrics.MessagesStored.Set(messageCount); CataloggerMetrics.MessageRateMinute = messageCount - CataloggerMetrics.MessageRateMinute; var process = Process.GetCurrentProcess(); CataloggerMetrics.ProcessPhysicalMemory.Set(process.WorkingSet64); CataloggerMetrics.ProcessVirtualMemory.Set(process.VirtualMemorySize64); CataloggerMetrics.ProcessPrivateMemory.Set(process.PrivateMemorySize64); CataloggerMetrics.ProcessThreads.Set(process.Threads.Count); CataloggerMetrics.ProcessHandles.Set(process.HandleCount); _logger.Information("Collected metrics in {Duration}", timer.ObserveDuration()); } } public class BackgroundMetricsCollectionService( ILogger logger, MetricsCollectionService innerService ) : BackgroundService { private readonly ILogger _logger = logger.ForContext(); protected override async Task ExecuteAsync(CancellationToken ct) { _logger.Information("Metrics are disabled, periodically collecting metrics manually"); using var timer = new PeriodicTimer(1.Minutes()); while (await timer.WaitForNextTickAsync(ct)) { _logger.Debug("Collecting metrics"); await innerService.CollectMetricsAsync(ct); } } }