add tooltip timestamp to max concurrent players

This commit is contained in:
RaidMax 2021-09-14 18:12:20 -05:00
parent 54e39fabb1
commit 68c1151191
6 changed files with 49 additions and 18 deletions

View File

@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
@ -20,14 +19,14 @@ namespace IW4MAdmin.Application.Misc
public class ServerDataViewer : IServerDataViewer public class ServerDataViewer : IServerDataViewer
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IDataValueCache<EFServerSnapshot, int> _snapshotCache; private readonly IDataValueCache<EFServerSnapshot, (int?, DateTime?)> _snapshotCache;
private readonly IDataValueCache<EFClient, (int, int)> _serverStatsCache; private readonly IDataValueCache<EFClient, (int, int)> _serverStatsCache;
private readonly IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> _clientHistoryCache; private readonly IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> _clientHistoryCache;
private readonly TimeSpan? _cacheTimeSpan = private readonly TimeSpan? _cacheTimeSpan =
Utilities.IsDevelopment ? TimeSpan.FromSeconds(1) : (TimeSpan?) TimeSpan.FromMinutes(1); Utilities.IsDevelopment ? TimeSpan.FromSeconds(1) : (TimeSpan?) TimeSpan.FromMinutes(1);
public ServerDataViewer(ILogger<ServerDataViewer> logger, IDataValueCache<EFServerSnapshot, int> snapshotCache, public ServerDataViewer(ILogger<ServerDataViewer> logger, IDataValueCache<EFServerSnapshot, (int?, DateTime?)> snapshotCache,
IDataValueCache<EFClient, (int, int)> serverStatsCache, IDataValueCache<EFClient, (int, int)> serverStatsCache,
IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> clientHistoryCache) IDataValueCache<EFServerSnapshot, List<ClientHistoryInfo>> clientHistoryCache)
{ {
@ -37,7 +36,7 @@ namespace IW4MAdmin.Application.Misc
_clientHistoryCache = clientHistoryCache; _clientHistoryCache = clientHistoryCache;
} }
public async Task<int> MaxConcurrentClientsAsync(long? serverId = null, TimeSpan? overPeriod = null, public async Task<(int?, DateTime?)> MaxConcurrentClientsAsync(long? serverId = null, TimeSpan? overPeriod = null,
CancellationToken token = default) CancellationToken token = default)
{ {
_snapshotCache.SetCacheItem(async (snapshots, cancellationToken) => _snapshotCache.SetCacheItem(async (snapshots, cancellationToken) =>
@ -45,26 +44,45 @@ namespace IW4MAdmin.Application.Misc
var oldestEntry = overPeriod.HasValue var oldestEntry = overPeriod.HasValue
? DateTime.UtcNow - overPeriod.Value ? DateTime.UtcNow - overPeriod.Value
: DateTime.UtcNow.AddDays(-1); : DateTime.UtcNow.AddDays(-1);
var maxClients = 0;
int? maxClients;
DateTime? maxClientsTime;
if (serverId != null) if (serverId != null)
{ {
maxClients = await snapshots.Where(snapshot => snapshot.ServerId == serverId) var clients = await snapshots.Where(snapshot => snapshot.ServerId == serverId)
.Where(snapshot => snapshot.CapturedAt >= oldestEntry) .Where(snapshot => snapshot.CapturedAt >= oldestEntry)
.MaxAsync(snapshot => (int?) snapshot.ClientCount, cancellationToken) ?? 0; .OrderByDescending(snapshot => snapshot.ClientCount)
.Select(snapshot => new
{
snapshot.ClientCount,
snapshot.CapturedAt
})
.FirstOrDefaultAsync(cancellationToken);
maxClients = clients?.ClientCount;
maxClientsTime = clients?.CapturedAt;
} }
else else
{ {
maxClients = await snapshots.Where(snapshot => snapshot.CapturedAt >= oldestEntry) var clients = await snapshots.Where(snapshot => snapshot.CapturedAt >= oldestEntry)
.GroupBy(snapshot => snapshot.PeriodBlock) .GroupBy(snapshot => snapshot.PeriodBlock)
.Select(grp => grp.Sum(snapshot => (int?) snapshot.ClientCount)) .Select(grp => new
.MaxAsync(cancellationToken) ?? 0; {
ClientCount = grp.Sum(snapshot => (int?) snapshot.ClientCount),
Time = grp.Max(snapshot => (DateTime?) snapshot.CapturedAt)
})
.OrderByDescending(snapshot => snapshot.ClientCount)
.FirstOrDefaultAsync(cancellationToken);
maxClients = clients?.ClientCount;
maxClientsTime = clients?.Time;
} }
_logger.LogDebug("Max concurrent clients since {Start} is {Clients}", oldestEntry, maxClients); _logger.LogDebug("Max concurrent clients since {Start} is {Clients}", oldestEntry, maxClients);
return maxClients; return (maxClients, maxClientsTime);
}, nameof(MaxConcurrentClientsAsync), _cacheTimeSpan); }, nameof(MaxConcurrentClientsAsync), _cacheTimeSpan);
try try
@ -74,7 +92,7 @@ namespace IW4MAdmin.Application.Misc
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Could not retrieve data for {Name}", nameof(MaxConcurrentClientsAsync)); _logger.LogError(ex, "Could not retrieve data for {Name}", nameof(MaxConcurrentClientsAsync));
return 0; return (null, null);
} }
} }

View File

@ -1,4 +1,5 @@
using static SharedLibraryCore.Server; using System;
using static SharedLibraryCore.Server;
namespace SharedLibraryCore.Dtos namespace SharedLibraryCore.Dtos
{ {
@ -9,6 +10,7 @@ namespace SharedLibraryCore.Dtos
public int TotalOccupiedClientSlots { get; set; } public int TotalOccupiedClientSlots { get; set; }
public int TotalAvailableClientSlots { get; set; } public int TotalAvailableClientSlots { get; set; }
public int MaxConcurrentClients { get; set; } public int MaxConcurrentClients { get; set; }
public DateTime MaxConcurrentClientsTime { get; set; }
/// <summary> /// <summary>
/// specifies the game name filter /// specifies the game name filter

View File

@ -19,7 +19,7 @@ namespace SharedLibraryCore.Interfaces
/// <param name="overPeriod">how far in the past to search</param> /// <param name="overPeriod">how far in the past to search</param>
/// <param name="token">CancellationToken</param> /// <param name="token">CancellationToken</param>
/// <returns></returns> /// <returns></returns>
Task<int> MaxConcurrentClientsAsync(long? serverId = null, TimeSpan? overPeriod = null, CancellationToken token = default); Task<(int?, DateTime?)> MaxConcurrentClientsAsync(long? serverId = null, TimeSpan? overPeriod = null, CancellationToken token = default);
/// <summary> /// <summary>
/// Gets the total number of clients connected and total clients connected in the given time frame /// Gets the total number of clients connected and total clients connected in the given time frame

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Diagnostics; using System;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos;
@ -33,7 +34,7 @@ namespace WebfrontCore.Controllers
ViewBag.Keywords = Localization["WEBFRONT_KEWORDS_HOME"]; ViewBag.Keywords = Localization["WEBFRONT_KEWORDS_HOME"];
var servers = Manager.GetServers().Where(_server => !game.HasValue || _server.GameName == game); var servers = Manager.GetServers().Where(_server => !game.HasValue || _server.GameName == game);
var maxConcurrentClients = await _serverDataViewer.MaxConcurrentClientsAsync(token: cancellationToken); var (clientCount, time) = await _serverDataViewer.MaxConcurrentClientsAsync(token: cancellationToken);
var (count, recentCount) = await _serverDataViewer.ClientCountsAsync(token: cancellationToken); var (count, recentCount) = await _serverDataViewer.ClientCountsAsync(token: cancellationToken);
var model = new IW4MAdminInfo() var model = new IW4MAdminInfo()
@ -42,7 +43,8 @@ namespace WebfrontCore.Controllers
TotalOccupiedClientSlots = servers.SelectMany(_server => _server.GetClientsAsList()).Count(), TotalOccupiedClientSlots = servers.SelectMany(_server => _server.GetClientsAsList()).Count(),
TotalClientCount = count, TotalClientCount = count,
RecentClientCount = recentCount, RecentClientCount = recentCount,
MaxConcurrentClients = maxConcurrentClients, MaxConcurrentClients = clientCount ?? 0,
MaxConcurrentClientsTime = time ?? DateTime.UtcNow,
Game = game, Game = game,
ActiveServerGames = Manager.GetServers().Select(_server => _server.GameName).Distinct().ToArray() ActiveServerGames = Manager.GetServers().Select(_server => _server.GameName).Distinct().ToArray()
}; };

View File

@ -11,7 +11,7 @@
<div class="col-xl-3 col-12"> <div class="col-xl-3 col-12">
<div class="text-muted text-center text-xl-left">@Html.Raw(formatTranslation("WEBFRONT_HOME_CLIENTS_ONLINE", Model.TotalOccupiedClientSlots, Model.TotalAvailableClientSlots))</div> <div class="text-muted text-center text-xl-left">@Html.Raw(formatTranslation("WEBFRONT_HOME_CLIENTS_ONLINE", Model.TotalOccupiedClientSlots, Model.TotalAvailableClientSlots))</div>
</div> </div>
<div class="col-xl-3 col-12"> <div class="col-xl-3 col-12 moment-date" title="@Model.MaxConcurrentClientsTime">
<div class="text-muted text-center text-xl-left">@Html.Raw(formatTranslation("WEBFRONT_HOME_MAX_CONCURRENT_CLIENTS", Model.MaxConcurrentClients.ToString("#,##0")))</div> <div class="text-muted text-center text-xl-left">@Html.Raw(formatTranslation("WEBFRONT_HOME_MAX_CONCURRENT_CLIENTS", Model.MaxConcurrentClients.ToString("#,##0")))</div>
</div> </div>
<div class="col-xl-3 col-12"> <div class="col-xl-3 col-12">

View File

@ -95,6 +95,15 @@ $(document).ready(function () {
historyChart.render(); historyChart.render();
charts[serverId] = historyChart; charts[serverId] = historyChart;
}); });
$('.moment-date').each((index, element) => {
const title = $(element).attr('title');
if (title !== undefined) {
const date = new Date(title);
$(element).attr('title', moment.utc(date).calendar());
}
});
}); });
setInterval(refreshClientActivity, 2000); setInterval(refreshClientActivity, 2000);