Files
LightlessServer/LightlessSyncServer/LightlessSyncServer/Services/SystemInfoService.cs

94 lines
4.5 KiB
C#

using LightlessSync.API.Dto;
using LightlessSync.API.SignalR;
using LightlessSyncServer.Hubs;
using LightlessSyncServer.Models;
using LightlessSyncShared.Data;
using LightlessSyncShared.Metrics;
using LightlessSyncShared.Services;
using LightlessSyncShared.Utils.Configuration;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using StackExchange.Redis.Extensions.Core.Abstractions;
namespace LightlessSyncServer.Services;
public sealed class SystemInfoService : BackgroundService
{
private readonly LightlessMetrics _lightlessMetrics;
private readonly IConfigurationService<ServerConfiguration> _config;
private readonly IDbContextFactory<LightlessDbContext> _dbContextFactory;
private readonly ILogger<SystemInfoService> _logger;
private readonly IHubContext<LightlessHub, ILightlessHub> _hubContext;
private readonly IRedisDatabase _redis;
public SystemInfoDto SystemInfoDto { get; private set; } = new();
public SystemInfoService(LightlessMetrics lightlessMetrics, IConfigurationService<ServerConfiguration> configurationService, IDbContextFactory<LightlessDbContext> dbContextFactory,
ILogger<SystemInfoService> logger, IHubContext<LightlessHub, ILightlessHub> hubContext, IRedisDatabase redisDb)
{
_lightlessMetrics = lightlessMetrics;
_config = configurationService;
_dbContextFactory = dbContextFactory;
_logger = logger;
_hubContext = hubContext;
_redis = redisDb;
}
public override async Task StartAsync(CancellationToken cancellationToken)
{
await base.StartAsync(cancellationToken).ConfigureAwait(false);
_logger.LogInformation("System Info Service started");
}
protected override async Task ExecuteAsync(CancellationToken ct)
{
var timeOut = _config.IsMain ? 15 : 30;
while (!ct.IsCancellationRequested)
{
try
{
ThreadPool.GetAvailableThreads(out int workerThreads, out int ioThreads);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableWorkerThreads, workerThreads);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableIOWorkerThreads, ioThreads);
var onlineUsers = (_redis.SearchKeysAsync("UID:*").GetAwaiter().GetResult()).Count();
var allLightfinderKeys = _redis.SearchKeysAsync("broadcast:*").GetAwaiter().GetResult().Where(c => !c.Contains("owner", StringComparison.Ordinal)).ToHashSet(StringComparer.Ordinal);
var allLightfinderItems = _redis.GetAllAsync<BroadcastRedisEntry>(allLightfinderKeys).GetAwaiter().GetResult();
var countLightFinderUsers = allLightfinderItems.Count;
var countLightFinderSyncshells = allLightfinderItems.Count(static l => !string.IsNullOrEmpty(l.Value.GID));
SystemInfoDto = new SystemInfoDto()
{
OnlineUsers = onlineUsers,
};
if (_config.IsMain)
{
_logger.LogInformation("Sending System Info, Online Users: {onlineUsers}", onlineUsers);
await _hubContext.Clients.All.Client_UpdateSystemInfo(SystemInfoDto).ConfigureAwait(false);
using var db = await _dbContextFactory.CreateDbContextAsync(ct).ConfigureAwait(false);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, onlineUsers);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeLightFinderConnections, countLightFinderUsers);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugePairs, db.ClientPairs.AsNoTracking().Count());
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugePairsPaused, db.Permissions.AsNoTracking().Count(p => p.IsPaused));
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeGroups, db.Groups.AsNoTracking().Count());
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeGroupPairs, db.GroupPairs.AsNoTracking().Count());
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeLightFinderGroups, countLightFinderSyncshells);
_lightlessMetrics.SetGaugeTo(MetricsAPI.GaugeUsersRegistered, db.Users.AsNoTracking().Count());
}
await Task.Delay(TimeSpan.FromSeconds(timeOut), ct).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to push system info");
}
}
}
}