rework metrics
This commit is contained in:
@@ -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) =>
|
||||
|
||||
@@ -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<MareHub> _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<MareHub> 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<ConnectionDto> 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);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="6.0.0" />
|
||||
<PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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<MareMetrics>();
|
||||
|
||||
metrics.SetGaugeTo(MetricsAPI.GaugePairs, context.ClientPairs.Count());
|
||||
metrics.SetGaugeTo(MetricsAPI.GaugePairsPaused, context.ClientPairs.Count(p => p.IsPaused));
|
||||
}
|
||||
|
||||
if (args.Length == 0 || args[0] != "dry")
|
||||
|
||||
@@ -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<string>
|
||||
{
|
||||
MetricsAPI.CounterInitializedConnections,
|
||||
MetricsAPI.CounterUserPushData,
|
||||
MetricsAPI.CounterUserPushDataTo,
|
||||
MetricsAPI.CounterUsersRegisteredDeleted,
|
||||
}, new List<string>
|
||||
{
|
||||
MetricsAPI.GaugeAuthorizedConnections,
|
||||
MetricsAPI.GaugeConnections,
|
||||
MetricsAPI.GaugePairs,
|
||||
MetricsAPI.GaugePairsPaused,
|
||||
MetricsAPI.GaugeAvailableIOWorkerThreads,
|
||||
MetricsAPI.GaugeAvailableWorkerThreads
|
||||
}));
|
||||
|
||||
services.AddGrpcClient<AuthService.AuthServiceClient>(c =>
|
||||
{
|
||||
c.Address = new Uri(mareConfig.GetValue<string>("ServiceAddress"));
|
||||
@@ -67,13 +86,6 @@ namespace MareSynchronosServer
|
||||
{
|
||||
c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } };
|
||||
});
|
||||
services.AddGrpcClient<MetricsService.MetricsServiceClient>(c =>
|
||||
{
|
||||
c.Address = new Uri(mareConfig.GetValue<string>("ServiceAddress"));
|
||||
}).ConfigureChannel(c =>
|
||||
{
|
||||
c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } };
|
||||
});
|
||||
services.AddGrpcClient<FileService.FileServiceClient>(c =>
|
||||
{
|
||||
c.Address = new Uri(mareConfig.GetValue<string>("StaticFileServiceAddress"));
|
||||
@@ -134,6 +146,9 @@ namespace MareSynchronosServer
|
||||
|
||||
app.UseWebSockets();
|
||||
|
||||
var metricServer = new KestrelMetricServer(4981);
|
||||
metricServer.Start();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
@@ -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<SystemInfoService> _logger;
|
||||
private readonly IHubContext<MareHub> _hubContext;
|
||||
private Timer _timer;
|
||||
public SystemInfoDto SystemInfoDto { get; private set; } = new();
|
||||
|
||||
public SystemInfoService(MetricsService.MetricsServiceClient metricsClient, IServiceProvider services, ILogger<SystemInfoService> logger, IHubContext<MareHub> hubContext)
|
||||
public SystemInfoService(MareMetrics mareMetrics, IServiceProvider services, ILogger<SystemInfoService> logger, IHubContext<MareHub> 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<MareDbContext>()!;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<MareDbContext>();
|
||||
|
||||
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<string, Counter> 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<string, Gauge> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<MareDbContext>();
|
||||
var metrics = services.GetRequiredService<MareMetrics>();
|
||||
|
||||
metrics.SetGaugeTo(MetricsAPI.GaugeUsersRegistered, dbContext.Users.Count());
|
||||
}
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Empty> IncreaseCounter(IncreaseCounterRequest request, ServerCallContext context)
|
||||
{
|
||||
metrics.IncCounterBy(request.CounterName, request.Value);
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
|
||||
public override Task<Empty> SetGauge(SetGaugeRequest request, ServerCallContext context)
|
||||
{
|
||||
metrics.SetGaugeTo(request.GaugeName, request.Value);
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
|
||||
public override Task<Empty> DecGauge(GaugeRequest request, ServerCallContext context)
|
||||
{
|
||||
metrics.DecGaugeBy(request.GaugeName, request.Value);
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
|
||||
public override Task<Empty> IncGauge(GaugeRequest request, ServerCallContext context)
|
||||
{
|
||||
metrics.IncGaugeBy(request.GaugeName, request.Value);
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
}
|
||||
@@ -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<MareMetrics>();
|
||||
services.AddSingleton(new MareMetrics(new List<string> {
|
||||
MetricsAPI.CounterAuthenticationRequests,
|
||||
MetricsAPI.CounterAuthenticationFailures,
|
||||
MetricsAPI.CounterAuthenticationCacheHits,
|
||||
MetricsAPI.CounterAuthenticationSuccesses
|
||||
}, new List<string>
|
||||
{
|
||||
MetricsAPI.GaugeUsersRegistered
|
||||
}));
|
||||
|
||||
services.AddSingleton<SecretKeyAuthenticationHandler>();
|
||||
services.AddSingleton<CleanupService>();
|
||||
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<AuthenticationService>();
|
||||
endpoints.MapGrpcService<MetricsService>();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using MareSynchronosShared.Data;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Prometheus;
|
||||
|
||||
namespace MareSynchronosShared.Metrics;
|
||||
|
||||
public class MareMetrics
|
||||
{
|
||||
public MareMetrics(List<string> countersToServe, List<string> 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<string, Counter> counters = new(StringComparer.Ordinal);
|
||||
|
||||
private readonly Dictionary<string, Gauge> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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<string, int64> 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;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace MareSynchronosStaticFilesServer;
|
||||
|
||||
public class CleanupService : IHostedService, IDisposable
|
||||
{
|
||||
private readonly MetricsService.MetricsServiceClient _metrics;
|
||||
private readonly MareMetrics _metrics;
|
||||
private readonly ILogger<CleanupService> _logger;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IConfiguration _configuration;
|
||||
private Timer? _timer;
|
||||
|
||||
public CleanupService(MetricsService.MetricsServiceClient metrics, ILogger<CleanupService> logger, IServiceProvider services, IConfiguration configuration)
|
||||
public CleanupService(MareMetrics metrics, ILogger<CleanupService> 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");
|
||||
|
||||
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
|
||||
});
|
||||
_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");
|
||||
|
||||
_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();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ public class FileService : MareSynchronosShared.Protos.FileService.FileServiceBa
|
||||
private readonly string _basePath;
|
||||
private readonly MareDbContext _mareDbContext;
|
||||
private readonly ILogger<FileService> _logger;
|
||||
private readonly MetricsService.MetricsServiceClient _metricsClient;
|
||||
private readonly MareMetrics _metricsClient;
|
||||
|
||||
public FileService(MareDbContext mareDbContext, IConfiguration configuration, ILogger<FileService> logger, MetricsService.MetricsServiceClient metricsClient)
|
||||
public FileService(MareDbContext mareDbContext, IConfiguration configuration, ILogger<FileService> 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)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.47.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="6.0.0" />
|
||||
<PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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<string> {
|
||||
}, new List<string>
|
||||
{
|
||||
MetricsAPI.GaugeFilesTotalSize,
|
||||
MetricsAPI.GaugeFilesTotal
|
||||
}));
|
||||
|
||||
services.AddGrpcClient<AuthService.AuthServiceClient>(c =>
|
||||
{
|
||||
c.Address = new Uri(mareSettings.GetValue<string>("ServiceAddress"));
|
||||
@@ -51,13 +61,6 @@ public class Startup
|
||||
{
|
||||
c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } };
|
||||
});
|
||||
services.AddGrpcClient<MetricsService.MetricsServiceClient>(c =>
|
||||
{
|
||||
c.Address = new Uri(mareSettings.GetValue<string>("ServiceAddress"));
|
||||
}).ConfigureChannel(c =>
|
||||
{
|
||||
c.ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } };
|
||||
});
|
||||
|
||||
services.AddDbContextPool<MareDbContext>(options =>
|
||||
{
|
||||
@@ -89,6 +92,9 @@ public class Startup
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
var metricServer = new KestrelMetricServer(4982);
|
||||
metricServer.Start();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
@@ -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": "*"
|
||||
|
||||
Reference in New Issue
Block a user