From ace31926dbcb24db41f1fc85a514854779b68d99 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Fri, 26 Aug 2022 02:22:19 +0200 Subject: [PATCH] rework metrics --- .../MareSynchronosServer/Hubs/MareHub.User.cs | 25 +++--- .../MareSynchronosServer/Hubs/MareHub.cs | 16 ++-- .../MareSynchronosServer.csproj | 1 + .../MareSynchronosServer/Program.cs | 7 +- .../MareSynchronosServer/Startup.cs | 29 +++++-- .../MareSynchronosServer/SystemInfoService.cs | 12 ++- .../SecretKeyAuthenticationHandler.cs | 1 - .../MareSynchronosServices/CleanupService.cs | 7 +- .../Discord/DiscordBot.cs | 4 +- .../Metrics/MareMetrics.cs | 85 ------------------- .../MareSynchronosServices/Program.cs | 13 +++ .../Services/MetricsService.cs | 40 --------- .../MareSynchronosServices/Startup.cs | 19 +++-- .../Metrics/MareMetrics.cs | 57 +++++++++++++ .../Metrics/MetricsAPI.cs | 1 + .../Protos/mareservices.proto | 22 ----- .../CleanupService.cs | 45 ++++------ .../FileService.cs | 16 ++-- .../MareSynchronosStaticFilesServer.csproj | 1 + .../Startup.cs | 20 +++-- .../appsettings.json | 2 +- 21 files changed, 179 insertions(+), 244 deletions(-) delete mode 100644 MareSynchronosServer/MareSynchronosServices/Metrics/MareMetrics.cs delete mode 100644 MareSynchronosServer/MareSynchronosServices/Services/MetricsService.cs create mode 100644 MareSynchronosServer/MareSynchronosShared/Metrics/MareMetrics.cs diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs index 4982bcf..d71adf6 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs @@ -55,12 +55,9 @@ namespace MareSynchronosServer.Hubs }, userEntry.CharacterIdentification).ConfigureAwait(false); } - await _metricsClient.DecGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugePairs, Value = ownPairData.Count + otherPairData.Count }).ConfigureAwait(false); - await _metricsClient.DecGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugePairsPaused, Value = ownPairData.Count(c => c.IsPaused) }).ConfigureAwait(false); - await _metricsClient.DecGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugeUsersRegistered, Value = 1 }).ConfigureAwait(false); + _mareMetrics.DecGauge(MetricsAPI.GaugePairs, ownPairData.Count + otherPairData.Count); + _mareMetrics.DecGauge(MetricsAPI.GaugePairsPaused, ownPairData.Count(c => c.IsPaused)); + _mareMetrics.IncCounter(MetricsAPI.CounterUsersRegisteredDeleted, 1); _dbContext.RemoveRange(otherPairData); _dbContext.Remove(userEntry); @@ -162,17 +159,15 @@ namespace MareSynchronosServer.Hubs await Clients.Users(otherEntries).SendAsync(Api.OnUserReceiveCharacterData, characterCache, user.CharacterIdentification).ConfigureAwait(false); - await _metricsClient.IncreaseCounterAsync(new IncreaseCounterRequest() - { CounterName = MetricsAPI.CounterUserPushData, Value = 1 }).ConfigureAwait(false); - await _metricsClient.IncreaseCounterAsync(new IncreaseCounterRequest() - { CounterName = MetricsAPI.CounterUserPushDataTo, Value = otherEntries.Count }).ConfigureAwait(false); + _mareMetrics.IncCounter(MetricsAPI.CounterUserPushData); + _mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, otherEntries.Count); } [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] [HubMethodName(Api.SendUserPairedClientAddition)] public async Task SendPairedClientAddition(string uid) { - if (uid == AuthenticatedUserId) return; + if (uid == AuthenticatedUserId || string.IsNullOrWhiteSpace(uid)) return; uid = uid.Trim(); var user = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false); @@ -223,7 +218,7 @@ namespace MareSynchronosServer.Hubs } } - await _metricsClient.IncGaugeAsync(new GaugeRequest() {GaugeName = MetricsAPI.GaugePairs, Value = 1}).ConfigureAwait(false); + _mareMetrics.IncGauge(MetricsAPI.GaugePairs); } [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] @@ -263,11 +258,11 @@ namespace MareSynchronosServer.Hubs if (isPaused) { - await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairsPaused, Value = 1 }).ConfigureAwait(false); + _mareMetrics.IncGauge(MetricsAPI.GaugePairsPaused); } else { - await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairsPaused, Value = 1 }).ConfigureAwait(false); + _mareMetrics.DecGauge(MetricsAPI.GaugePairsPaused); } } @@ -311,7 +306,7 @@ namespace MareSynchronosServer.Hubs } } - await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugePairs, Value = 1 }).ConfigureAwait(false); + _mareMetrics.DecGauge(MetricsAPI.GaugePairs); } private ClientPair OppositeEntry(string otherUID) => diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs index eec99d9..4305ee8 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs @@ -19,7 +19,7 @@ namespace MareSynchronosServer.Hubs { public partial class MareHub : Hub { - private readonly MetricsService.MetricsServiceClient _metricsClient; + private readonly MareMetrics _mareMetrics; private readonly AuthService.AuthServiceClient _authServiceClient; private readonly FileService.FileServiceClient _fileServiceClient; private readonly SystemInfoService _systemInfoService; @@ -27,10 +27,10 @@ namespace MareSynchronosServer.Hubs private readonly ILogger _logger; private readonly MareDbContext _dbContext; private readonly Uri cdnFullUri; - public MareHub(MetricsService.MetricsServiceClient metricsClient, AuthService.AuthServiceClient authServiceClient, FileService.FileServiceClient fileServiceClient, + public MareHub(MareMetrics mareMetrics, AuthService.AuthServiceClient authServiceClient, FileService.FileServiceClient fileServiceClient, MareDbContext mareDbContext, ILogger logger, SystemInfoService systemInfoService, IConfiguration configuration, IHttpContextAccessor contextAccessor) { - _metricsClient = metricsClient; + _mareMetrics = mareMetrics; _authServiceClient = authServiceClient; _fileServiceClient = fileServiceClient; _systemInfoService = systemInfoService; @@ -44,7 +44,7 @@ namespace MareSynchronosServer.Hubs [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] public async Task Heartbeat(string characterIdentification) { - await _metricsClient.IncreaseCounterAsync(new() { CounterName = MetricsAPI.CounterInitializedConnections, Value = 1 }).ConfigureAwait(false); + _mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections); var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; @@ -66,7 +66,7 @@ namespace MareSynchronosServer.Hubs } else if (string.IsNullOrEmpty(user.CharacterIdentification)) { - await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeAuthorizedConnections, Value = 1 }).ConfigureAwait(false); + _mareMetrics.IncGauge(MetricsAPI.GaugeAuthorizedConnections); } user.LastLoggedIn = DateTime.UtcNow; @@ -91,18 +91,18 @@ namespace MareSynchronosServer.Hubs public override async Task OnConnectedAsync() { _logger.LogInformation("Connection from {ip}", contextAccessor.GetIpAddress()); - await _metricsClient.IncGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeConnections, Value = 1 }).ConfigureAwait(false); + _mareMetrics.IncGauge(MetricsAPI.GaugeConnections); await base.OnConnectedAsync().ConfigureAwait(false); } public override async Task OnDisconnectedAsync(Exception exception) { - await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeConnections, Value = 1 }).ConfigureAwait(false); + _mareMetrics.DecGauge(MetricsAPI.GaugeConnections); var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false); if (user != null && !string.IsNullOrEmpty(user.CharacterIdentification)) { - await _metricsClient.DecGaugeAsync(new GaugeRequest() { GaugeName = MetricsAPI.GaugeAuthorizedConnections, Value = 1 }).ConfigureAwait(false); + _mareMetrics.DecGauge(MetricsAPI.GaugeAuthorizedConnections); _logger.LogInformation("Disconnect from {id}", AuthenticatedUserId); diff --git a/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj index a430c2a..8ac0f94 100644 --- a/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj +++ b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj @@ -29,6 +29,7 @@ + diff --git a/MareSynchronosServer/MareSynchronosServer/Program.cs b/MareSynchronosServer/MareSynchronosServer/Program.cs index d8c41a8..2208144 100644 --- a/MareSynchronosServer/MareSynchronosServer/Program.cs +++ b/MareSynchronosServer/MareSynchronosServer/Program.cs @@ -6,8 +6,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using System.Collections.Generic; using MareSynchronosShared.Data; +using MareSynchronosShared.Metrics; namespace MareSynchronosServer { @@ -36,6 +36,11 @@ namespace MareSynchronosServer context.RemoveRange(unfinishedRegistrations); context.RemoveRange(looseFiles); context.SaveChanges(); + + var metrics = services.GetRequiredService(); + + metrics.SetGaugeTo(MetricsAPI.GaugePairs, context.ClientPairs.Count()); + metrics.SetGaugeTo(MetricsAPI.GaugePairsPaused, context.ClientPairs.Count(p => p.IsPaused)); } if (args.Length == 0 || args[0] != "dry") diff --git a/MareSynchronosServer/MareSynchronosServer/Startup.cs b/MareSynchronosServer/MareSynchronosServer/Startup.cs index 685ac02..da3986d 100644 --- a/MareSynchronosServer/MareSynchronosServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServer/Startup.cs @@ -16,6 +16,9 @@ using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; using MareSynchronosShared.Protos; using Grpc.Net.Client.Configuration; +using Prometheus; +using MareSynchronosShared.Metrics; +using System.Collections.Generic; namespace MareSynchronosServer { @@ -60,6 +63,22 @@ namespace MareSynchronosServer } }; + services.AddSingleton(new MareMetrics(new List + { + MetricsAPI.CounterInitializedConnections, + MetricsAPI.CounterUserPushData, + MetricsAPI.CounterUserPushDataTo, + MetricsAPI.CounterUsersRegisteredDeleted, + }, new List + { + MetricsAPI.GaugeAuthorizedConnections, + MetricsAPI.GaugeConnections, + MetricsAPI.GaugePairs, + MetricsAPI.GaugePairsPaused, + MetricsAPI.GaugeAvailableIOWorkerThreads, + MetricsAPI.GaugeAvailableWorkerThreads + })); + services.AddGrpcClient(c => { c.Address = new Uri(mareConfig.GetValue("ServiceAddress")); @@ -67,13 +86,6 @@ namespace MareSynchronosServer { c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }; }); - services.AddGrpcClient(c => - { - c.Address = new Uri(mareConfig.GetValue("ServiceAddress")); - }).ConfigureChannel(c => - { - c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }; - }); services.AddGrpcClient(c => { c.Address = new Uri(mareConfig.GetValue("StaticFileServiceAddress")); @@ -134,6 +146,9 @@ namespace MareSynchronosServer app.UseWebSockets(); + var metricServer = new KestrelMetricServer(4981); + metricServer.Start(); + app.UseAuthentication(); app.UseAuthorization(); diff --git a/MareSynchronosServer/MareSynchronosServer/SystemInfoService.cs b/MareSynchronosServer/MareSynchronosServer/SystemInfoService.cs index 670c5e9..b960906 100644 --- a/MareSynchronosServer/MareSynchronosServer/SystemInfoService.cs +++ b/MareSynchronosServer/MareSynchronosServer/SystemInfoService.cs @@ -16,16 +16,16 @@ namespace MareSynchronosServer; public class SystemInfoService : IHostedService, IDisposable { - private readonly MetricsService.MetricsServiceClient metricsClient; + private readonly MareMetrics _mareMetrics; private readonly IServiceProvider _services; private readonly ILogger _logger; private readonly IHubContext _hubContext; private Timer _timer; public SystemInfoDto SystemInfoDto { get; private set; } = new(); - public SystemInfoService(MetricsService.MetricsServiceClient metricsClient, IServiceProvider services, ILogger logger, IHubContext hubContext) + public SystemInfoService(MareMetrics mareMetrics, IServiceProvider services, ILogger logger, IHubContext hubContext) { - this.metricsClient = metricsClient; + _mareMetrics = mareMetrics; _services = services; _logger = logger; _hubContext = hubContext; @@ -48,10 +48,8 @@ public class SystemInfoService : IHostedService, IDisposable using var scope = _services.CreateScope(); using var db = scope.ServiceProvider.GetService()!; - metricsClient.SetGauge(new SetGaugeRequest() - { GaugeName = MetricsAPI.GaugeAvailableWorkerThreads, Value = workerThreads }); - metricsClient.SetGauge(new SetGaugeRequest() - { GaugeName = MetricsAPI.GaugeAvailableIOWorkerThreads, Value = ioThreads }); + _mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableWorkerThreads, workerThreads); + _mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableIOWorkerThreads, ioThreads); var users = db.Users.Count(c => c.CharacterIdentification != null); diff --git a/MareSynchronosServer/MareSynchronosServices/Authentication/SecretKeyAuthenticationHandler.cs b/MareSynchronosServer/MareSynchronosServices/Authentication/SecretKeyAuthenticationHandler.cs index 6d0e62e..c20e18b 100644 --- a/MareSynchronosServer/MareSynchronosServices/Authentication/SecretKeyAuthenticationHandler.cs +++ b/MareSynchronosServer/MareSynchronosServices/Authentication/SecretKeyAuthenticationHandler.cs @@ -5,7 +5,6 @@ using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; -using MareSynchronosServices.Metrics; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Protos; diff --git a/MareSynchronosServer/MareSynchronosServices/CleanupService.cs b/MareSynchronosServer/MareSynchronosServices/CleanupService.cs index 7d527fc..313b976 100644 --- a/MareSynchronosServer/MareSynchronosServices/CleanupService.cs +++ b/MareSynchronosServer/MareSynchronosServices/CleanupService.cs @@ -1,5 +1,4 @@ using MareSynchronosServices.Authentication; -using MareSynchronosServices.Metrics; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Models; @@ -140,9 +139,9 @@ namespace MareSynchronosServices .Where(u => u.OtherUser.UID == user.UID).ToList(); - metrics.DecGaugeBy(MetricsAPI.GaugePairs, ownPairData.Count + otherPairData.Count); - metrics.DecGaugeBy(MetricsAPI.GaugePairsPaused, ownPairData.Count + ownPairData.Count(c => c.IsPaused)); - metrics.DecGaugeBy(MetricsAPI.GaugeUsersRegistered, ownPairData.Count + 1); + metrics.DecGauge(MetricsAPI.GaugePairs, ownPairData.Count + otherPairData.Count); + metrics.DecGauge(MetricsAPI.GaugePairsPaused, ownPairData.Count + ownPairData.Count(c => c.IsPaused)); + metrics.DecGauge(MetricsAPI.GaugeUsersRegistered, ownPairData.Count + 1); dbContext.RemoveRange(otherPairData); dbContext.Remove(auth); diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs index 57c4034..25b6b6c 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/DiscordBot.cs @@ -9,9 +9,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Discord; -using Discord.Rest; using Discord.WebSocket; -using MareSynchronosServices.Metrics; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Models; @@ -262,7 +260,7 @@ public class DiscordBot : IHostedService logger.LogInformation("User registered: {userUID}", user.UID); - metrics.IncGaugeBy(MetricsAPI.GaugeUsersRegistered, 1); + metrics.IncGauge(MetricsAPI.GaugeUsersRegistered, 1); lodestoneAuth.StartedAt = null; lodestoneAuth.User = user; diff --git a/MareSynchronosServer/MareSynchronosServices/Metrics/MareMetrics.cs b/MareSynchronosServer/MareSynchronosServices/Metrics/MareMetrics.cs deleted file mode 100644 index 8abe97e..0000000 --- a/MareSynchronosServer/MareSynchronosServices/Metrics/MareMetrics.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MareSynchronosShared.Data; -using MareSynchronosShared.Metrics; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Prometheus; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MareSynchronosServices.Metrics; - -public class MareMetrics -{ - public MareMetrics(IServiceProvider services) - { - using var scope = services.CreateScope(); - using var dbContext = scope.ServiceProvider.GetService(); - - gauges[MetricsAPI.GaugeUsersRegistered].IncTo(dbContext.Users.Count()); - gauges[MetricsAPI.GaugePairs].IncTo(dbContext.ClientPairs.Count()); - gauges[MetricsAPI.GaugePairsPaused].IncTo(dbContext.ClientPairs.Count(p => p.IsPaused)); - gauges[MetricsAPI.GaugeFilesTotal].IncTo(dbContext.Files.Count()); - } - - private readonly Dictionary counters = new() - { - { MetricsAPI.CounterInitializedConnections, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterInitializedConnections, "Initialized Connections") }, - { MetricsAPI.CounterUserPushData, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterUserPushData, "Users pushing data") }, - { MetricsAPI.CounterUserPushDataTo, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterUserPushDataTo, "Users Receiving Data") }, - { MetricsAPI.CounterAuthenticationRequests, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterAuthenticationRequests, "Authentication Requests") }, - { MetricsAPI.CounterAuthenticationCacheHits, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterAuthenticationCacheHits, "Authentication Requests Cache Hits") }, - { MetricsAPI.CounterAuthenticationFailures, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterAuthenticationFailures, "Authentication Requests Failed") }, - { MetricsAPI.CounterAuthenticationSuccesses, Prometheus.Metrics.CreateCounter(MetricsAPI.CounterAuthenticationSuccesses, "Authentication Requests Success") }, - }; - - private readonly Dictionary gauges = new() - { - { MetricsAPI.GaugeConnections, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeConnections, "Unauthorized Connections") }, - { MetricsAPI.GaugeAuthorizedConnections, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeAuthorizedConnections, "Authorized Connections") }, - { MetricsAPI.GaugeAvailableIOWorkerThreads, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeAvailableIOWorkerThreads, "Available Threadpool IO Workers") }, - { MetricsAPI.GaugeAvailableWorkerThreads, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeAvailableWorkerThreads, "Aavailable Threadpool Workers") }, - { MetricsAPI.GaugeUsersRegistered, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeUsersRegistered, "Total Registrations") }, - { MetricsAPI.GaugePairs, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugePairs, "Total Pairs") }, - { MetricsAPI.GaugePairsPaused, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugePairsPaused, "Total Paused Pairs") }, - { MetricsAPI.GaugeFilesTotal, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeFilesTotal, "Total uploaded files") }, - { MetricsAPI.GaugeFilesTotalSize, Prometheus.Metrics.CreateGauge(MetricsAPI.GaugeFilesTotalSize, "Total uploaded files (bytes)") }, - }; - - public void SetGaugeTo(string gaugeName, double value) - { - if (gauges.ContainsKey(gaugeName)) - { - gauges[gaugeName].IncTo(value); - } - } - - public void IncGaugeBy(string gaugeName, double value) - { - if (gauges.ContainsKey(gaugeName)) - { - gauges[gaugeName].Inc(value); - } - } - - public void DecGaugeBy(string gaugeName, double value) - { - if (gauges.ContainsKey(gaugeName)) - { - gauges[gaugeName].Dec(value); - } - } - - public void IncCounter(string counterName) - { - IncCounterBy(counterName, 1); - } - - public void IncCounterBy(string counterName, double value) - { - if (counters.ContainsKey(counterName)) - { - counters[counterName].Inc(value); - } - } -} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServices/Program.cs b/MareSynchronosServer/MareSynchronosServices/Program.cs index 0e78505..6e61499 100644 --- a/MareSynchronosServer/MareSynchronosServices/Program.cs +++ b/MareSynchronosServer/MareSynchronosServices/Program.cs @@ -1,7 +1,11 @@ using MareSynchronosServices; +using MareSynchronosShared.Data; +using MareSynchronosShared.Metrics; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; +using System.Linq; public class Program { @@ -10,6 +14,15 @@ public class Program var hostBuilder = CreateHostBuilder(args); var host = hostBuilder.Build(); + using (var scope = host.Services.CreateScope()) + { + var services = scope.ServiceProvider; + using var dbContext = services.GetRequiredService(); + var metrics = services.GetRequiredService(); + + metrics.SetGaugeTo(MetricsAPI.GaugeUsersRegistered, dbContext.Users.Count()); + } + host.Run(); } diff --git a/MareSynchronosServer/MareSynchronosServices/Services/MetricsService.cs b/MareSynchronosServer/MareSynchronosServices/Services/MetricsService.cs deleted file mode 100644 index 44e8fb1..0000000 --- a/MareSynchronosServer/MareSynchronosServices/Services/MetricsService.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Grpc.Core; -using MareSynchronosServices.Metrics; -using MareSynchronosShared.Protos; -using System.Threading.Tasks; - -namespace MareSynchronosServices.Services; - -public class MetricsService : MareSynchronosShared.Protos.MetricsService.MetricsServiceBase -{ - private readonly MareMetrics metrics; - - public MetricsService(MareMetrics metrics) - { - this.metrics = metrics; - } - - public override Task IncreaseCounter(IncreaseCounterRequest request, ServerCallContext context) - { - metrics.IncCounterBy(request.CounterName, request.Value); - return Task.FromResult(new Empty()); - } - - public override Task SetGauge(SetGaugeRequest request, ServerCallContext context) - { - metrics.SetGaugeTo(request.GaugeName, request.Value); - return Task.FromResult(new Empty()); - } - - public override Task DecGauge(GaugeRequest request, ServerCallContext context) - { - metrics.DecGaugeBy(request.GaugeName, request.Value); - return Task.FromResult(new Empty()); - } - - public override Task IncGauge(GaugeRequest request, ServerCallContext context) - { - metrics.IncGaugeBy(request.GaugeName, request.Value); - return Task.FromResult(new Empty()); - } -} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServices/Startup.cs b/MareSynchronosServer/MareSynchronosServices/Startup.cs index 791bfac..b480130 100644 --- a/MareSynchronosServer/MareSynchronosServices/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServices/Startup.cs @@ -1,16 +1,15 @@ -using MareSynchronosServer; using MareSynchronosServices.Authentication; using MareSynchronosServices.Discord; -using MareSynchronosServices.Metrics; using MareSynchronosServices.Services; -using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; +using MareSynchronosShared.Metrics; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Prometheus; +using System.Collections.Generic; namespace MareSynchronosServices; @@ -34,7 +33,16 @@ public class Startup options.EnableThreadSafetyChecks(false); }, Configuration.GetValue("DbContextPoolSize", 1024)); - services.AddSingleton(); + services.AddSingleton(new MareMetrics(new List { + MetricsAPI.CounterAuthenticationRequests, + MetricsAPI.CounterAuthenticationFailures, + MetricsAPI.CounterAuthenticationCacheHits, + MetricsAPI.CounterAuthenticationSuccesses + }, new List + { + MetricsAPI.GaugeUsersRegistered + })); + services.AddSingleton(); services.AddSingleton(); services.AddTransient(_ => Configuration); @@ -47,13 +55,12 @@ public class Startup { app.UseRouting(); - var metricServer = new KestrelMetricServer(4980); + var metricServer = new KestrelMetricServer(4982); metricServer.Start(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService(); - endpoints.MapGrpcService(); }); } } \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosShared/Metrics/MareMetrics.cs b/MareSynchronosServer/MareSynchronosShared/Metrics/MareMetrics.cs new file mode 100644 index 0000000..6fdb1d0 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosShared/Metrics/MareMetrics.cs @@ -0,0 +1,57 @@ +using MareSynchronosShared.Data; +using Microsoft.Extensions.DependencyInjection; +using Prometheus; + +namespace MareSynchronosShared.Metrics; + +public class MareMetrics +{ + public MareMetrics(List countersToServe, List gaugesToServe) + { + foreach(var counter in countersToServe) + { + counters.Add(counter, Prometheus.Metrics.CreateCounter(counter, counter)); + } + + foreach(var gauge in gaugesToServe) + { + gauges.Add(gauge, Prometheus.Metrics.CreateGauge(gauge, gauge)); + } + } + + private readonly Dictionary counters = new(StringComparer.Ordinal); + + private readonly Dictionary gauges = new(StringComparer.Ordinal); + + public void SetGaugeTo(string gaugeName, double value) + { + if (gauges.ContainsKey(gaugeName)) + { + gauges[gaugeName].IncTo(value); + } + } + + public void IncGauge(string gaugeName, double value = 1.0) + { + if (gauges.ContainsKey(gaugeName)) + { + gauges[gaugeName].Inc(value); + } + } + + public void DecGauge(string gaugeName, double value = 1.0) + { + if (gauges.ContainsKey(gaugeName)) + { + gauges[gaugeName].Dec(value); + } + } + + public void IncCounter(string counterName, double value = 1.0) + { + if (counters.ContainsKey(counterName)) + { + counters[counterName].Inc(value); + } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosShared/Metrics/MetricsAPI.cs b/MareSynchronosServer/MareSynchronosShared/Metrics/MetricsAPI.cs index 1d420e9..3b6187f 100644 --- a/MareSynchronosServer/MareSynchronosShared/Metrics/MetricsAPI.cs +++ b/MareSynchronosServer/MareSynchronosShared/Metrics/MetricsAPI.cs @@ -8,6 +8,7 @@ public class MetricsAPI public const string GaugeAvailableWorkerThreads = "mare_available_threadpool"; public const string GaugeAvailableIOWorkerThreads = "mare_available_threadpool_io"; public const string GaugeUsersRegistered = "mare_users_registered"; + public const string CounterUsersRegisteredDeleted = "mare_users_registered_deleted"; public const string GaugePairs = "mare_pairs"; public const string GaugePairsPaused = "mare_pairs_paused"; public const string GaugeFilesTotal = "mare_files"; diff --git a/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto b/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto index 1aba480..5d38bbc 100644 --- a/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto +++ b/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto @@ -10,13 +10,6 @@ service AuthService { rpc ClearUnauthorized (Empty) returns (Empty); } -service MetricsService { - rpc IncreaseCounter (IncreaseCounterRequest) returns (Empty); - rpc SetGauge (SetGaugeRequest) returns (Empty); - rpc DecGauge (GaugeRequest) returns (Empty); - rpc IncGauge (GaugeRequest) returns (Empty); -} - service FileService { rpc UploadFile (UploadFileRequest) returns (Empty); rpc GetFileSizes (FileSizeRequest) returns (FileSizeResponse); @@ -43,21 +36,6 @@ message FileSizeResponse { map hashToFileSize = 1; } -message GaugeRequest { - string gaugeName = 1; - double value = 2; -} - -message SetGaugeRequest { - string gaugeName = 1; - double value = 2; -} - -message IncreaseCounterRequest { - string counterName = 1; - double value = 2; -} - message RemoveAuthRequest { string uid = 1; } diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/CleanupService.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/CleanupService.cs index 6c4f489..37e87c5 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/CleanupService.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/CleanupService.cs @@ -16,13 +16,13 @@ namespace MareSynchronosStaticFilesServer; public class CleanupService : IHostedService, IDisposable { - private readonly MetricsService.MetricsServiceClient _metrics; + private readonly MareMetrics _metrics; private readonly ILogger _logger; private readonly IServiceProvider _services; private readonly IConfiguration _configuration; private Timer? _timer; - public CleanupService(MetricsService.MetricsServiceClient metrics, ILogger logger, IServiceProvider services, IConfiguration configuration) + public CleanupService(MareMetrics metrics, ILogger logger, IServiceProvider services, IConfiguration configuration) { _metrics = metrics; _logger = logger; @@ -30,31 +30,22 @@ public class CleanupService : IHostedService, IDisposable _configuration = configuration.GetRequiredSection("MareSynchronos"); } - public async Task StartAsync(CancellationToken cancellationToken) + public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Cleanup Service started"); - _ = Task.Run(async () => - { - _logger.LogInformation("Calculating initial files"); + _logger.LogInformation("Calculating initial files"); - DirectoryInfo dir = new DirectoryInfo(_configuration["CacheDirectory"]); - var allFiles = dir.GetFiles(); - await _metrics.SetGaugeAsync(new SetGaugeRequest() - { - GaugeName = MetricsAPI.GaugeFilesTotalSize, - Value = allFiles.Sum(f => f.Length) - }); - await _metrics.SetGaugeAsync(new SetGaugeRequest() - { - GaugeName = MetricsAPI.GaugeFilesTotal, - Value = allFiles.Length - }); + DirectoryInfo dir = new DirectoryInfo(_configuration["CacheDirectory"]); + var allFiles = dir.GetFiles(); + _metrics.SetGaugeTo(MetricsAPI.GaugeFilesTotalSize, allFiles.Sum(f => f.Length)); + _metrics.SetGaugeTo(MetricsAPI.GaugeFilesTotal, allFiles.Length); - _logger.LogInformation("Initial file calculation finished, starting periodic cleanup task"); + _logger.LogInformation("Initial file calculation finished, starting periodic cleanup task"); - _timer = new Timer(CleanUp, null, TimeSpan.FromSeconds(15), TimeSpan.FromMinutes(10)); - }); + _timer = new Timer(CleanUp, null, TimeSpan.FromSeconds(15), TimeSpan.FromMinutes(10)); + + return Task.CompletedTask; } private void CleanUp(object? state) @@ -86,8 +77,8 @@ public class CleanupService : IHostedService, IDisposable } else if (fi.LastAccessTime < prevTime) { - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = fi.Length }); - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotalSize, fi.Length); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotal); _logger.LogInformation("File outdated: {fileName}", fileName); dbContext.Files.Remove(file); fi.Delete(); @@ -101,8 +92,8 @@ public class CleanupService : IHostedService, IDisposable { if (!allFilesHashes.Contains(file.Name.ToUpperInvariant())) { - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = file.Length }); - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotalSize, file.Length); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotal); file.Delete(); _logger.LogInformation("File not in DB, deleting: {fileName}", file.FullName); } @@ -131,8 +122,8 @@ public class CleanupService : IHostedService, IDisposable removedHashes.Add(oldestFile.Name.ToLower()); allLocalFiles.Remove(oldestFile); totalCacheSizeInBytes -= oldestFile.Length; - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = oldestFile.Length }); - _metrics.DecGauge(new() { GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotalSize, oldestFile.Length); + _metrics.DecGauge(MetricsAPI.GaugeFilesTotal); oldestFile.Delete(); } diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/FileService.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/FileService.cs index ee184e2..08aafb0 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/FileService.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/FileService.cs @@ -17,9 +17,9 @@ public class FileService : MareSynchronosShared.Protos.FileService.FileServiceBa private readonly string _basePath; private readonly MareDbContext _mareDbContext; private readonly ILogger _logger; - private readonly MetricsService.MetricsServiceClient _metricsClient; + private readonly MareMetrics _metricsClient; - public FileService(MareDbContext mareDbContext, IConfiguration configuration, ILogger logger, MetricsService.MetricsServiceClient metricsClient) + public FileService(MareDbContext mareDbContext, IConfiguration configuration, ILogger logger, MareMetrics metricsClient) { _basePath = configuration.GetRequiredSection("MareSynchronos")["CacheDirectory"]; _mareDbContext = mareDbContext; @@ -37,10 +37,8 @@ public class FileService : MareSynchronosShared.Protos.FileService.FileServiceBa await File.WriteAllBytesAsync(filePath, byteData); file.Uploaded = true; - await _metricsClient.IncGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = byteData.Length }).ConfigureAwait(false); - await _metricsClient.IncGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }).ConfigureAwait(false); + _metricsClient.IncGauge(MetricsAPI.GaugeFilesTotal, 1); + _metricsClient.IncGauge(MetricsAPI.GaugeFilesTotalSize, byteData.Length); await _mareDbContext.SaveChangesAsync().ConfigureAwait(false); _logger.LogInformation("User {user} uploaded file {hash}", request.Uploader, request.Hash); @@ -62,10 +60,8 @@ public class FileService : MareSynchronosShared.Protos.FileService.FileServiceBa { _mareDbContext.Files.Remove(file); - await _metricsClient.DecGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugeFilesTotalSize, Value = fi.Length }).ConfigureAwait(false); - await _metricsClient.DecGaugeAsync(new GaugeRequest() - { GaugeName = MetricsAPI.GaugeFilesTotal, Value = 1 }).ConfigureAwait(false); + _metricsClient.DecGauge(MetricsAPI.GaugeFilesTotal, 1); + _metricsClient.DecGauge(MetricsAPI.GaugeFilesTotalSize, fi.Length); } } catch (Exception ex) diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/MareSynchronosStaticFilesServer.csproj b/MareSynchronosServer/MareSynchronosStaticFilesServer/MareSynchronosStaticFilesServer.csproj index 0751e36..43e5401 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/MareSynchronosStaticFilesServer.csproj +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/MareSynchronosStaticFilesServer.csproj @@ -21,6 +21,7 @@ + diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs index affbcb4..dd3d4ee 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs @@ -1,6 +1,7 @@ using Grpc.Net.Client.Configuration; using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; +using MareSynchronosShared.Metrics; using MareSynchronosShared.Protos; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; @@ -10,7 +11,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; +using Prometheus; using System; +using System.Collections.Generic; namespace MareSynchronosStaticFilesServer; @@ -44,6 +47,13 @@ public class Startup } }; + services.AddSingleton(new MareMetrics(new List { + }, new List + { + MetricsAPI.GaugeFilesTotalSize, + MetricsAPI.GaugeFilesTotal + })); + services.AddGrpcClient(c => { c.Address = new Uri(mareSettings.GetValue("ServiceAddress")); @@ -51,13 +61,6 @@ public class Startup { c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }; }); - services.AddGrpcClient(c => - { - c.Address = new Uri(mareSettings.GetValue("ServiceAddress")); - }).ConfigureChannel(c => - { - c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }; - }); services.AddDbContextPool(options => { @@ -89,6 +92,9 @@ public class Startup app.UseRouting(); + var metricServer = new KestrelMetricServer(4982); + metricServer.Start(); + app.UseAuthentication(); app.UseAuthorization(); diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/appsettings.json b/MareSynchronosServer/MareSynchronosStaticFilesServer/appsettings.json index 630b597..63c89c8 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/appsettings.json +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/appsettings.json @@ -22,7 +22,7 @@ "MareSynchronos": { "CacheSizeHardLimitInGiB": -1, "UnusedFileRetentionPeriodInDays": 7, - "CacheDirectory": "G:\\ServerTest", // do not delete this key and set it to the path where the files will be stored + "CacheDirectory": "G:\\ServerTest", "ServiceAddress": "http://localhost:5002" }, "AllowedHosts": "*"