Add basic InfluxDB reporter

This commit is contained in:
Ske
2019-07-16 23:34:22 +02:00
parent 2d58705e85
commit 02b41413b3
7 changed files with 125 additions and 6 deletions

View File

@@ -18,6 +18,7 @@ using Microsoft.Extensions.DependencyInjection;
using NodaTime;
using Npgsql;
using Npgsql.Logging;
using PluralKit.Core;
using Sentry;
using Sentry.Extensibility;
@@ -94,7 +95,15 @@ namespace PluralKit.Bot
.AddTransient<MessageStore>()
.AddTransient<SwitchStore>()
.AddSingleton<IMetrics>(_ => AppMetrics.CreateDefaultBuilder().Build())
.AddSingleton<IMetrics>(svc =>
{
var cfg = svc.GetRequiredService<CoreConfig>();
var builder = AppMetrics.CreateDefaultBuilder();
if (cfg.InfluxUrl != null && cfg.InfluxDb != null)
builder.Report.ToInfluxDb(cfg.InfluxUrl, cfg.InfluxDb);
return builder.Build();
})
.AddSingleton<PeriodicStatCollector>()
.BuildServiceProvider();
}
@@ -106,14 +115,16 @@ namespace PluralKit.Bot
private ProxyService _proxy;
private Timer _updateTimer;
private IMetrics _metrics;
private PeriodicStatCollector _collector;
public Bot(IServiceProvider services, IDiscordClient client, CommandService commands, ProxyService proxy, IMetrics metrics)
public Bot(IServiceProvider services, IDiscordClient client, CommandService commands, ProxyService proxy, IMetrics metrics, PeriodicStatCollector collector)
{
this._services = services;
this._client = client as DiscordShardedClient;
this._commands = commands;
this._proxy = proxy;
_metrics = metrics;
_collector = collector;
}
public async Task Init()
@@ -132,18 +143,28 @@ namespace PluralKit.Bot
_client.MessageDeleted += async (message, channel) => _proxy.HandleMessageDeletedAsync(message, channel).CatchException(HandleRuntimeError);
}
// Method called every 60 seconds
private async Task UpdatePeriodic()
{
// Method called every 60 seconds
// Change bot status
await _client.SetGameAsync($"pk;help | in {_client.Guilds.Count} servers");
await _collector.CollectStats();
await Task.WhenAll(((IMetricsRoot) _metrics).ReportRunner.RunAllAsync());
}
private async Task ShardReady(DiscordSocketClient shardClient)
{
//_updateTimer = new Timer((_) => UpdatePeriodic(), null, 0, 60*1000);
Console.WriteLine($"Shard #{shardClient.ShardId} connected to {shardClient.Guilds.Sum(g => g.Channels.Count)} channels in {shardClient.Guilds.Count} guilds.");
//Console.WriteLine($"PluralKit started as {_client.CurrentUser.Username}#{_client.CurrentUser.Discriminator} ({_client.CurrentUser.Id}).");
if (shardClient.ShardId == 0)
{
_updateTimer = new Timer((_) => UpdatePeriodic().CatchException(HandleRuntimeError), null, 0, 60*1000);
Console.WriteLine(
$"PluralKit started as {_client.CurrentUser.Username}#{_client.CurrentUser.Discriminator} ({_client.CurrentUser.Id}).");
}
}
private async Task CommandExecuted(Optional<CommandInfo> cmd, ICommandContext ctx, IResult _result)

View File

@@ -9,7 +9,10 @@ namespace PluralKit.Bot
public static MeterOptions MessagesReceived => new MeterOptions {Name = "Messages processed", MeasurementUnit = Unit.Events, RateUnit = TimeUnit.Seconds, Context = "Bot"};
public static MeterOptions MessagesProxied => new MeterOptions {Name = "Messages proxied", MeasurementUnit = Unit.Events, RateUnit = TimeUnit.Seconds, Context = "Bot"};
public static MeterOptions CommandsRun => new MeterOptions {Name = "Commands run", MeasurementUnit = Unit.Commands, RateUnit = TimeUnit.Seconds, Context = "Bot"};
public static GaugeOptions MembersTotal => new GaugeOptions {Name = "Members total", MeasurementUnit = Unit.None, Context = "Bot"};
public static GaugeOptions MembersOnline => new GaugeOptions {Name = "Members online", MeasurementUnit = Unit.None, Context = "Bot"};
public static GaugeOptions Guilds => new GaugeOptions {Name = "Guilds", MeasurementUnit = Unit.None, Context = "Bot"};
public static GaugeOptions Channels => new GaugeOptions {Name = "Channels", MeasurementUnit = Unit.None, Context = "Bot"};
public static GaugeOptions DatabasePoolSize => new GaugeOptions { Name = "Database pool size", Context = "Database" };
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using App.Metrics;
using Discord;
using Discord.WebSocket;
using PluralKit.Core;
namespace PluralKit.Bot
{
public class PeriodicStatCollector
{
private DiscordShardedClient _client;
private IMetrics _metrics;
private SystemStore _systems;
private MemberStore _members;
private SwitchStore _switches;
private MessageStore _messages;
public PeriodicStatCollector(IDiscordClient client, IMetrics metrics, SystemStore systems, MemberStore members, SwitchStore switches, MessageStore messages)
{
_client = (DiscordShardedClient) client;
_metrics = metrics;
_systems = systems;
_members = members;
_switches = switches;
_messages = messages;
}
public async Task CollectStats()
{
// Aggregate guild/channel stats
_metrics.Measure.Gauge.SetValue(BotMetrics.Guilds, _client.Guilds.Count);
_metrics.Measure.Gauge.SetValue(BotMetrics.Channels, _client.Guilds.Sum(g => g.TextChannels.Count));
// Aggregate member stats
var usersKnown = new HashSet<ulong>();
var usersOnline = new HashSet<ulong>();
foreach (var guild in _client.Guilds)
foreach (var user in guild.Users)
{
usersKnown.Add(user.Id);
if (user.Status == UserStatus.Online) usersOnline.Add(user.Id);
}
_metrics.Measure.Gauge.SetValue(BotMetrics.MembersTotal, usersKnown.Count);
_metrics.Measure.Gauge.SetValue(BotMetrics.MembersOnline, usersOnline.Count);
// Aggregate DB stats
_metrics.Measure.Gauge.SetValue(CoreMetrics.SystemCount, await _systems.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MemberCount, await _members.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.SwitchCount, await _switches.Count());
_metrics.Measure.Gauge.SetValue(CoreMetrics.MessageCount, await _messages.Count());
}
}
}