Skip to content

Commit

Permalink
Handle statistics with Prometheus
Browse files Browse the repository at this point in the history
  • Loading branch information
matte-ek committed Jul 8, 2023
1 parent 82e7658 commit eb0cdfc
Show file tree
Hide file tree
Showing 18 changed files with 125 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="2.5.1" />
<PackageReference Include="MudBlazor" Version="6.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="prometheus-net" Version="8.0.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
Expand Down
4 changes: 1 addition & 3 deletions BanchoMultiplayerBot.Host.Web/BotService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using BanchoMultiplayerBot.Host.Web.Statistics;

namespace BanchoMultiplayerBot.Host.Web
namespace BanchoMultiplayerBot.Host.Web
{
public class BotService : Bot, IDisposable
{
Expand Down
2 changes: 1 addition & 1 deletion BanchoMultiplayerBot.Host.Web/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@

Bot.Lobbies.ForEach(x => _playerCount += x.MultiplayerLobby.Players.Count);
Bot.Lobbies.ForEach(x => _maxPlayerCount += (x.Configuration.Size.HasValue == true ? x.Configuration.Size.Value : 0));
Bot.Lobbies.ForEach(x => _gamesPlayed += x.Statistics.GamesPlayed);
//Bot.Lobbies.ForEach(x => _gamesPlayed += x.Statistics.GamesPlayed);
UpdateBanchoConnection();

Expand Down
7 changes: 6 additions & 1 deletion BanchoMultiplayerBot.Host.Web/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using BanchoMultiplayerBot.Host.Web.Auth;
using BanchoMultiplayerBot.Host.Web.Extra;
using BanchoMultiplayerBot.Host.Web.Log;
using BanchoMultiplayerBot.Host.Web.Statistics;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Authorization;
Expand All @@ -11,6 +10,7 @@
using MudBlazor.Services;
using Serilog;
using Microsoft.FeatureManagement;
using Prometheus;

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
Expand Down Expand Up @@ -66,6 +66,11 @@
options.Transports = HttpTransportType.WebSockets;
});

if (app.Configuration.GetSection("FeatureManagement").GetValue<bool>("StatisticsController", false))
{
app.UseMetricServer("/api/statistics/metrics");
}

app.MapFallbackToPage("/_Host");

app.MapControllers();
Expand Down
71 changes: 0 additions & 71 deletions BanchoMultiplayerBot.Host.Web/Statistics/StatisticsController.cs

This file was deleted.

17 changes: 0 additions & 17 deletions BanchoMultiplayerBot.Host.Web/Statistics/StatisticsLobbyData.cs

This file was deleted.

29 changes: 0 additions & 29 deletions BanchoMultiplayerBot.Host.Web/Statistics/StatisticsSnapshot.cs

This file was deleted.

1 change: 1 addition & 0 deletions BanchoMultiplayerBot.sln.DotSettings.user
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt;&#xD;
&lt;Assembly Path="C:\Users\matte\CLionProjects\BanchoSharp\BanchoSharp\bin\Release\net6.0\BanchoSharp.dll" /&gt;&#xD;
&lt;/AssemblyExplorer&gt;</s:String>

<s:Boolean x:Key="/Default/UserDictionary/Words/=beatmap/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
1 change: 1 addition & 0 deletions BanchoMultiplayerBot/BanchoMultiplayerBot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="MudBlazor" Version="6.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="prometheus-net" Version="8.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions BanchoMultiplayerBot/Behaviour/AutoHostRotateBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private void OnUserMessage(IPrivateIrcMessage message)

OnQueueUpdated();

_lobby.Statistics.HostSkipCount++;
_lobby.Bot.RuntimeInfo.Statistics.HostSkipCount.WithLabels(_lobby.LobbyLabel).Inc();

return;
}
Expand All @@ -179,7 +179,7 @@ private void OnAdminMessage(IPrivateIrcMessage message)
SkipCurrentPlayer();
OnQueueUpdated();

_lobby.Statistics.HostSkipCount++;
_lobby.Bot.RuntimeInfo.Statistics.HostSkipCount.WithLabels(_lobby.LobbyLabel).Inc();
}

if (message.Content.StartsWith("!sethost "))
Expand Down
15 changes: 13 additions & 2 deletions BanchoMultiplayerBot/Behaviour/MapManagerBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class MapManagerBehaviour : IBotBehaviour

public int CurrentBeatmapSetId { get; private set; }
public int CurrentBeatmapId { get; private set; }
public int CurrentBeatmapLength { get; private set; }
public string CurrentBeatmapName { get; private set; } = string.Empty;

public bool ValidMapPicked { get; private set; } = true;
Expand All @@ -40,6 +41,7 @@ public class MapManagerBehaviour : IBotBehaviour
private bool _hostValidMapPicked = true;

private DateTime _matchStartTime = DateTime.Now;
private DateTime _matchFinishTime = DateTime.Now;
private DateTime _beatmapRejectTime = DateTime.Now;

private Mods _roomMods;
Expand Down Expand Up @@ -119,6 +121,10 @@ private async void OnSettingsUpdated()
private void OnMatchFinished()
{
IsValidatingMap = false;

_matchFinishTime = DateTime.Now;

_lobby.Bot.RuntimeInfo.Statistics.MapLength.WithLabels(_lobby.LobbyLabel).Observe(CurrentBeatmapLength);
}

private void OnMatchStarted()
Expand Down Expand Up @@ -232,6 +238,11 @@ private async Task EnsureBeatmapLimits(BeatmapModel beatmap, int id)

CurrentBeatmapName = $"{beatmap.Artist} - {beatmap.Title}";
CurrentBeatmapId = id;
CurrentBeatmapLength = beatmap.TotalLength == null
? 0
: int.Parse(beatmap.TotalLength, CultureInfo.InvariantCulture);

_lobby.Bot.RuntimeInfo.Statistics.MapPickTime.WithLabels(_lobby.LobbyLabel).Observe((DateTime.Now - _matchFinishTime).TotalSeconds);

ValidMapPicked = true;

Expand All @@ -254,7 +265,7 @@ private async Task EnsureBeatmapLimits(BeatmapModel beatmap, int id)

SetBeatmap(_beatmapFallbackId);

_lobby.Statistics.MapViolationCount++;
_lobby.Bot.RuntimeInfo.Statistics.MapViolations.WithLabels(_lobby.LobbyLabel).Inc();

if (IsBannedBeatmap(beatmap))
{
Expand Down Expand Up @@ -441,7 +452,7 @@ private bool IsAllowedBeatmapLength(BeatmapModel beatmap)

var mapLength = int.Parse(beatmap.TotalLength, CultureInfo.InvariantCulture);

return _lobby.Configuration.MaximumMapLength >= mapLength && mapLength >= _lobby.Configuration.MinimumMapLength ;
return _lobby.Configuration.MaximumMapLength >= mapLength && mapLength >= _lobby.Configuration.MinimumMapLength;
}

private bool IsAllowedBeatmapGameMode(BeatmapModel beatmap)
Expand Down
44 changes: 44 additions & 0 deletions BanchoMultiplayerBot/Behaviour/StatisticsBehaviour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace BanchoMultiplayerBot.Behaviour;

/// <summary>
/// Behaviour to provide some anonymous statistics for the bot, such as "games played",
/// "games aborted", "player count", "unique amount of players last hour".
/// </summary>
public class StatisticsBehaviour : IBotBehaviour
{
private Lobby _lobby = null!;
private readonly List<Tuple<string, DateTime>> _players = new();

public void Setup(Lobby lobby)
{
_lobby = lobby;

_lobby.MultiplayerLobby.OnMatchFinished += () =>
{
_lobby.Bot.RuntimeInfo.Statistics.GamesPlayed.WithLabels(_lobby.LobbyLabel).Inc();
};

_lobby.MultiplayerLobby.OnMatchAborted += () =>
{
_lobby.Bot.RuntimeInfo.Statistics.GamesAborted.WithLabels(_lobby.LobbyLabel).Inc();
};

_lobby.MultiplayerLobby.OnPlayerJoined += (e) =>
{
if (_players.All(x => x.Item1 != e.Name))
{
_players.Add(new Tuple<string, DateTime>(e.Name, DateTime.Now));
}

_players.RemoveAll(x => DateTime.Now > x.Item2.AddHours(1));

_lobby.Bot.RuntimeInfo.Statistics.Players.WithLabels(_lobby.LobbyLabel).Set(_lobby.MultiplayerLobby.Players.Count);
_lobby.Bot.RuntimeInfo.Statistics.UniquePlayers.WithLabels(_lobby.LobbyLabel).Set(_players.Count);
};

_lobby.MultiplayerLobby.OnPlayerDisconnected += (e) =>
{
_lobby.Bot.RuntimeInfo.Statistics.Players.WithLabels(_lobby.LobbyLabel).Set(_lobby.MultiplayerLobby.Players.Count);
};
}
}
10 changes: 8 additions & 2 deletions BanchoMultiplayerBot/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,13 @@ public async Task RunAsync()
// Events for logging purposes
Client.OnPrivateMessageReceived += e =>
{
RuntimeInfo.MessagesReceived++;
RuntimeInfo.Statistics.MessagesReceived.Inc();
Log.Information($"[{e.Recipient}] {e.Sender}: {e.Content}");
};

Client.OnPrivateMessageSent += e =>
{
RuntimeInfo.MessagesSent++;
RuntimeInfo.Statistics.MessagesSent.Inc();
Log.Information($"[{e.Recipient}] {e.Sender}: {e.Content}");
};

Expand Down Expand Up @@ -383,6 +383,8 @@ private void ClientOnAuthenticated()
OnBotReady?.Invoke();

Task.Run(RunConnectionWatchdog);

RuntimeInfo.Statistics.IsConnected.Set(1);
}

/// <summary>
Expand Down Expand Up @@ -476,6 +478,8 @@ private async Task RunConnectionWatchdog()

RuntimeInfo.HadNetworkConnectionIssue = true;
RuntimeInfo.LastConnectionIssueTime = DateTime.Now;

RuntimeInfo.Statistics.IsConnected.Set(0);

SaveBotState();

Expand Down Expand Up @@ -553,6 +557,8 @@ private async Task RunMessagePump()
continue;
}

RuntimeInfo.Statistics.MessageSendQueue.Set(_messageQueue.Count);

bool shouldThrottle;

do
Expand Down
8 changes: 2 additions & 6 deletions BanchoMultiplayerBot/Data/BotRuntimeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ public class BotRuntimeInfo
/// Time when bot last had networking issues
/// </summary>
public DateTime LastConnectionIssueTime { get; set; }

public int MessagesSent { get; set; }
public int MessagesReceived { get; set; }

public int ApiRequests { get; set; }
public int ApiErrors { get; set; }

public BotStatistics Statistics { get; } = new();

}
30 changes: 30 additions & 0 deletions BanchoMultiplayerBot/Data/BotStatistics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Prometheus;

namespace BanchoMultiplayerBot.Data;

/// <summary>
/// All statistics available through the metric endpoint if enabled. All statistics provided by the bot is anonymous.
/// </summary>
public class BotStatistics
{

public Gauge IsConnected { get; } = Metrics.CreateGauge("IsConnected", "If the bot is connected to Bancho.");

public Counter MessagesSent { get; } = Metrics.CreateCounter("MessagesSent", "Number of messages sent");
public Counter MessagesReceived { get; } = Metrics.CreateCounter("MessagesReceived", "Number of messages received");
public Gauge MessageSendQueue { get; } = Metrics.CreateGauge("MessageQueue", "Numbers of messages currently in queue to be sent.");

public Counter ApiRequests { get; } = Metrics.CreateCounter("TotalApiRequests", "Total amount of API requests.");
public Counter ApiErrors { get; } = Metrics.CreateCounter("TotalApiErrors", "Total amount of API errors.");
public Histogram ApiRequestTime { get; } = Metrics.CreateHistogram("ApiRequestTime", "Time for each API request.");

public Gauge Players { get; } = Metrics.CreateGauge("Players", "Total amount of players in each lobby", "Lobby");
public Gauge UniquePlayers { get; } = Metrics.CreateGauge("UniquePlayers", "Amount of unique players per hour", "Lobby");
public Gauge MapViolations { get; } = Metrics.CreateGauge("MapViolations", "Total amount of map violations in each lobby", "Lobby");
public Gauge GamesPlayed { get; } = Metrics.CreateGauge("GamesPlayed", "Total amount of games played in each lobby", "Lobby");
public Gauge GamesAborted { get; } = Metrics.CreateGauge("GamesAborted", "Total amount of games aborted in each lobby", "Lobby");
public Gauge HostSkipCount { get; } = Metrics.CreateGauge("HostSkipCount", "Total amount of host skips in each lobby", "Lobby");
public Histogram MapLength { get; } = Metrics.CreateHistogram("MapLength", "Length of the last map played", "Lobby");
public Histogram MapPickTime { get; } = Metrics.CreateHistogram("MapPickTime", "Time it took to pick a map", "Lobby");

}
Loading

0 comments on commit eb0cdfc

Please sign in to comment.