| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  | using System.Diagnostics; | 
					
						
							|  |  |  | using Foxnouns.Backend.Database; | 
					
						
							|  |  |  | using Microsoft.EntityFrameworkCore; | 
					
						
							|  |  |  | using NodaTime; | 
					
						
							|  |  |  | using Prometheus; | 
					
						
							| 
									
										
										
										
											2024-12-08 15:07:25 +01:00
										 |  |  | using ITimer = Prometheus.ITimer; | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Foxnouns.Backend.Services; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-02 00:28:07 +02:00
										 |  |  | public class MetricsCollectionService(ILogger logger, IServiceProvider services, IClock clock) | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     private readonly ILogger _logger = logger.ForContext<MetricsCollectionService>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static readonly Duration Month = Duration.FromDays(30); | 
					
						
							|  |  |  |     private static readonly Duration Week = Duration.FromDays(7); | 
					
						
							|  |  |  |     private static readonly Duration Day = Duration.FromDays(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public async Task CollectMetricsAsync(CancellationToken ct = default) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-12-08 15:07:25 +01:00
										 |  |  |         ITimer timer = FoxnounsMetrics.MetricsCollectionTime.NewTimer(); | 
					
						
							|  |  |  |         Instant now = clock.GetCurrentInstant(); | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-08 15:07:25 +01:00
										 |  |  |         await using AsyncServiceScope scope = services.CreateAsyncScope(); | 
					
						
							|  |  |  |         // ReSharper disable once SuggestVarOrType_SimpleTypes | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  |         await using var db = scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-08 15:07:25 +01:00
										 |  |  |         List<Instant>? users = await db | 
					
						
							|  |  |  |             .Users.Where(u => !u.Deleted) | 
					
						
							|  |  |  |             .Select(u => u.LastActive) | 
					
						
							|  |  |  |             .ToListAsync(ct); | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  |         FoxnounsMetrics.UsersCount.Set(users.Count); | 
					
						
							|  |  |  |         FoxnounsMetrics.UsersActiveMonthCount.Set(users.Count(i => i > now - Month)); | 
					
						
							|  |  |  |         FoxnounsMetrics.UsersActiveWeekCount.Set(users.Count(i => i > now - Week)); | 
					
						
							|  |  |  |         FoxnounsMetrics.UsersActiveDayCount.Set(users.Count(i => i > now - Day)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-08 15:07:25 +01:00
										 |  |  |         int memberCount = await db | 
					
						
							| 
									
										
										
										
											2024-10-02 00:28:07 +02:00
										 |  |  |             .Members.Include(m => m.User) | 
					
						
							|  |  |  |             .Where(m => !m.Unlisted && !m.User.ListHidden && !m.User.Deleted) | 
					
						
							|  |  |  |             .CountAsync(ct); | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  |         FoxnounsMetrics.MemberCount.Set(memberCount); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var process = Process.GetCurrentProcess(); | 
					
						
							|  |  |  |         FoxnounsMetrics.ProcessPhysicalMemory.Set(process.WorkingSet64); | 
					
						
							|  |  |  |         FoxnounsMetrics.ProcessVirtualMemory.Set(process.VirtualMemorySize64); | 
					
						
							|  |  |  |         FoxnounsMetrics.ProcessPrivateMemory.Set(process.PrivateMemorySize64); | 
					
						
							|  |  |  |         FoxnounsMetrics.ProcessThreads.Set(process.Threads.Count); | 
					
						
							|  |  |  |         FoxnounsMetrics.ProcessHandles.Set(process.HandleCount); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-02 00:28:07 +02:00
										 |  |  |         _logger.Information( | 
					
						
							|  |  |  |             "Collected metrics in {DurationMilliseconds} ms", | 
					
						
							|  |  |  |             timer.ObserveDuration().TotalMilliseconds | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-02 00:28:07 +02:00
										 |  |  | public class BackgroundMetricsCollectionService( | 
					
						
							|  |  |  |     ILogger logger, | 
					
						
							|  |  |  |     MetricsCollectionService metricsCollectionService | 
					
						
							|  |  |  | ) : BackgroundService | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     private readonly ILogger _logger = logger.ForContext<BackgroundMetricsCollectionService>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected override async Task ExecuteAsync(CancellationToken ct) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _logger.Information("Metrics are disabled, periodically collecting metrics manually"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1)); | 
					
						
							|  |  |  |         while (await timer.WaitForNextTickAsync(ct)) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-12-02 18:06:19 +01:00
										 |  |  |             _logger.Debug("Collecting metrics manually"); | 
					
						
							| 
									
										
										
										
											2024-09-09 14:50:00 +02:00
										 |  |  |             await metricsCollectionService.CollectMetricsAsync(ct); | 
					
						
							| 
									
										
										
										
											2024-09-03 17:00:14 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-10-02 00:28:07 +02:00
										 |  |  | } |