Refactor Sentry scope enrichment
This commit is contained in:
parent
f927450352
commit
f97ceac1fb
@ -47,6 +47,8 @@ namespace PluralKit.Bot
|
|||||||
_client.DebugLogger.LogMessageReceived += FrameworkLog;
|
_client.DebugLogger.LogMessageReceived += FrameworkLog;
|
||||||
|
|
||||||
// HandleEvent takes a type parameter, automatically inferred by the event type
|
// HandleEvent takes a type parameter, automatically inferred by the event type
|
||||||
|
// It will then look up an IEventHandler<TypeOfEvent> in the DI container and call that object's handler method
|
||||||
|
// For registering new ones, see Modules.cs
|
||||||
_client.MessageCreated += HandleEvent;
|
_client.MessageCreated += HandleEvent;
|
||||||
_client.MessageDeleted += HandleEvent;
|
_client.MessageDeleted += HandleEvent;
|
||||||
_client.MessageUpdated += HandleEvent;
|
_client.MessageUpdated += HandleEvent;
|
||||||
@ -69,8 +71,14 @@ namespace PluralKit.Bot
|
|||||||
async Task HandleEventInner()
|
async Task HandleEventInner()
|
||||||
{
|
{
|
||||||
var serviceScope = _services.BeginLifetimeScope();
|
var serviceScope = _services.BeginLifetimeScope();
|
||||||
|
|
||||||
|
// Find an event handler that can handle the type of event (<T>) we're given
|
||||||
var handler = serviceScope.Resolve<IEventHandler<T>>();
|
var handler = serviceScope.Resolve<IEventHandler<T>>();
|
||||||
|
|
||||||
|
// Also, find a Sentry enricher for the event type (if one is present), and ask it to put some event data in the Sentry scope
|
||||||
|
var sentryEnricher = serviceScope.ResolveOptional<ISentryEnricher<T>>();
|
||||||
|
sentryEnricher?.Enrich(serviceScope.Resolve<Scope>(), evt);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await handler.Handle(evt);
|
await handler.Handle(evt);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using App.Metrics;
|
using App.Metrics;
|
||||||
@ -129,21 +128,6 @@ namespace PluralKit.Bot
|
|||||||
{
|
{
|
||||||
_metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
|
_metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived);
|
||||||
_lastMessageCache.AddMessage(evt.Channel.Id, evt.Message.Id);
|
_lastMessageCache.AddMessage(evt.Channel.Id, evt.Message.Id);
|
||||||
|
|
||||||
// Add message info as Sentry breadcrumb
|
|
||||||
_sentryScope.AddBreadcrumb(evt.Message.Content, "event.message", data: new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{"user", evt.Author.Id.ToString()},
|
|
||||||
{"channel", evt.Channel.Id.ToString()},
|
|
||||||
{"guild", evt.Channel.GuildId.ToString()},
|
|
||||||
{"message", evt.Message.Id.ToString()},
|
|
||||||
});
|
|
||||||
_sentryScope.SetTag("shard", evt.Client.ShardId.ToString());
|
|
||||||
|
|
||||||
// Also report information about the bot's permissions in the channel
|
|
||||||
// We get a lot of permission errors so this'll be useful for determining problems
|
|
||||||
var perms = evt.Channel.BotPermissions();
|
|
||||||
_sentryScope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,37 +12,19 @@ namespace PluralKit.Bot
|
|||||||
public class MessageDeleted: IEventHandler<MessageDeleteEventArgs>, IEventHandler<MessageBulkDeleteEventArgs>
|
public class MessageDeleted: IEventHandler<MessageDeleteEventArgs>, IEventHandler<MessageBulkDeleteEventArgs>
|
||||||
{
|
{
|
||||||
private readonly ProxyService _proxy;
|
private readonly ProxyService _proxy;
|
||||||
private readonly Scope _sentryScope;
|
|
||||||
|
|
||||||
public MessageDeleted(Scope sentryScope, ProxyService proxy)
|
public MessageDeleted(ProxyService proxy)
|
||||||
{
|
{
|
||||||
_sentryScope = sentryScope;
|
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Handle(MessageDeleteEventArgs evt)
|
public Task Handle(MessageDeleteEventArgs evt)
|
||||||
{
|
{
|
||||||
_sentryScope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"channel", evt.Channel.Id.ToString()},
|
|
||||||
{"guild", evt.Channel.GuildId.ToString()},
|
|
||||||
{"message", evt.Message.Id.ToString()},
|
|
||||||
});
|
|
||||||
_sentryScope.SetTag("shard", evt.Client.ShardId.ToString());
|
|
||||||
|
|
||||||
return _proxy.HandleMessageDeletedAsync(evt);
|
return _proxy.HandleMessageDeletedAsync(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Handle(MessageBulkDeleteEventArgs evt)
|
public Task Handle(MessageBulkDeleteEventArgs evt)
|
||||||
{
|
{
|
||||||
_sentryScope.AddBreadcrumb("", "event.messageDelete", data: new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"channel", evt.Channel.Id.ToString()},
|
|
||||||
{"guild", evt.Channel.Id.ToString()},
|
|
||||||
{"messages", string.Join(",", evt.Messages.Select(m => m.Id))},
|
|
||||||
});
|
|
||||||
_sentryScope.SetTag("shard", evt.Client.ShardId.ToString());
|
|
||||||
|
|
||||||
return _proxy.HandleMessageBulkDeleteAsync(evt);
|
return _proxy.HandleMessageBulkDeleteAsync(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,14 +36,6 @@ namespace PluralKit.Bot
|
|||||||
// Also, if this is in DMs don't bother either
|
// Also, if this is in DMs don't bother either
|
||||||
if (evt.Channel.Guild == null) return;
|
if (evt.Channel.Guild == null) return;
|
||||||
|
|
||||||
_sentryScope.AddBreadcrumb(evt.Message.Content ?? "<unknown>", "event.messageEdit", data: new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"channel", evt.Channel.Id.ToString()},
|
|
||||||
{"guild", evt.Channel.GuildId.ToString()},
|
|
||||||
{"message", evt.Message.Id.ToString()}
|
|
||||||
});
|
|
||||||
_sentryScope.SetTag("shard", evt.Client.ShardId.ToString());
|
|
||||||
|
|
||||||
// If this isn't the last message in the channel, don't do anything
|
// If this isn't the last message in the channel, don't do anything
|
||||||
if (_lastMessageCache.GetLastMessage(evt.Channel.Id) != evt.Message.Id) return;
|
if (_lastMessageCache.GetLastMessage(evt.Channel.Id) != evt.Message.Id) return;
|
||||||
|
|
||||||
|
@ -10,25 +10,14 @@ namespace PluralKit.Bot
|
|||||||
public class ReactionAdded: IEventHandler<MessageReactionAddEventArgs>
|
public class ReactionAdded: IEventHandler<MessageReactionAddEventArgs>
|
||||||
{
|
{
|
||||||
private readonly ProxyService _proxy;
|
private readonly ProxyService _proxy;
|
||||||
private readonly Scope _sentryScope;
|
|
||||||
|
|
||||||
public ReactionAdded(ProxyService proxy, Scope sentryScope)
|
public ReactionAdded(ProxyService proxy)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
_sentryScope = sentryScope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Handle(MessageReactionAddEventArgs evt)
|
public Task Handle(MessageReactionAddEventArgs evt)
|
||||||
{
|
{
|
||||||
_sentryScope.AddBreadcrumb("", "event.reaction", data: new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"user", evt.User.Id.ToString()},
|
|
||||||
{"channel", (evt.Channel?.Id ?? 0).ToString()},
|
|
||||||
{"guild", (evt.Channel?.GuildId ?? 0).ToString()},
|
|
||||||
{"message", evt.Message.Id.ToString()},
|
|
||||||
{"reaction", evt.Emoji.Name}
|
|
||||||
});
|
|
||||||
_sentryScope.SetTag("shard", evt.Client.ShardId.ToString());
|
|
||||||
return _proxy.HandleReactionAddedAsync(evt);
|
return _proxy.HandleReactionAddedAsync(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,13 @@ namespace PluralKit.Bot
|
|||||||
|
|
||||||
// Sentry stuff
|
// Sentry stuff
|
||||||
builder.Register(_ => new Scope(null)).AsSelf().InstancePerLifetimeScope();
|
builder.Register(_ => new Scope(null)).AsSelf().InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<SentryEnricher>()
|
||||||
|
.As<ISentryEnricher<MessageCreateEventArgs>>()
|
||||||
|
.As<ISentryEnricher<MessageDeleteEventArgs>>()
|
||||||
|
.As<ISentryEnricher<MessageUpdateEventArgs>>()
|
||||||
|
.As<ISentryEnricher<MessageBulkDeleteEventArgs>>()
|
||||||
|
.As<ISentryEnricher<MessageReactionAddEventArgs>>()
|
||||||
|
.SingleInstance();
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
builder.Register(c => new HttpClient
|
builder.Register(c => new HttpClient
|
||||||
|
93
PluralKit.Bot/Utils/SentryUtils.cs
Normal file
93
PluralKit.Bot/Utils/SentryUtils.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.EventArgs;
|
||||||
|
|
||||||
|
using Sentry;
|
||||||
|
|
||||||
|
namespace PluralKit.Bot
|
||||||
|
{
|
||||||
|
public interface ISentryEnricher<T> where T: DiscordEventArgs
|
||||||
|
{
|
||||||
|
void Enrich(Scope scope, T evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SentryEnricher:
|
||||||
|
ISentryEnricher<MessageCreateEventArgs>,
|
||||||
|
ISentryEnricher<MessageDeleteEventArgs>,
|
||||||
|
ISentryEnricher<MessageUpdateEventArgs>,
|
||||||
|
ISentryEnricher<MessageBulkDeleteEventArgs>,
|
||||||
|
ISentryEnricher<MessageReactionAddEventArgs>
|
||||||
|
{
|
||||||
|
// TODO: should this class take the Scope by dependency injection instead?
|
||||||
|
// Would allow us to create a centralized "chain of handlers" where this class could just be registered as an entry in
|
||||||
|
|
||||||
|
public void Enrich(Scope scope, MessageCreateEventArgs evt)
|
||||||
|
{
|
||||||
|
scope.AddBreadcrumb(evt.Message.Content, "event.message", data: new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{"user", evt.Author.Id.ToString()},
|
||||||
|
{"channel", evt.Channel.Id.ToString()},
|
||||||
|
{"guild", evt.Channel.GuildId.ToString()},
|
||||||
|
{"message", evt.Message.Id.ToString()},
|
||||||
|
});
|
||||||
|
scope.SetTag("shard", evt.Client.ShardId.ToString());
|
||||||
|
|
||||||
|
// Also report information about the bot's permissions in the channel
|
||||||
|
// We get a lot of permission errors so this'll be useful for determining problems
|
||||||
|
var perms = evt.Channel.BotPermissions();
|
||||||
|
scope.AddBreadcrumb(perms.ToPermissionString(), "permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enrich(Scope scope, MessageDeleteEventArgs evt)
|
||||||
|
{
|
||||||
|
scope.AddBreadcrumb("", "event.messageDelete",
|
||||||
|
data: new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{"channel", evt.Channel.Id.ToString()},
|
||||||
|
{"guild", evt.Channel.GuildId.ToString()},
|
||||||
|
{"message", evt.Message.Id.ToString()},
|
||||||
|
});
|
||||||
|
scope.SetTag("shard", evt.Client.ShardId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enrich(Scope scope, MessageUpdateEventArgs evt)
|
||||||
|
{
|
||||||
|
scope.AddBreadcrumb(evt.Message.Content ?? "<unknown>", "event.messageEdit",
|
||||||
|
data: new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{"channel", evt.Channel.Id.ToString()},
|
||||||
|
{"guild", evt.Channel.GuildId.ToString()},
|
||||||
|
{"message", evt.Message.Id.ToString()}
|
||||||
|
});
|
||||||
|
scope.SetTag("shard", evt.Client.ShardId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enrich(Scope scope, MessageBulkDeleteEventArgs evt)
|
||||||
|
{
|
||||||
|
scope.AddBreadcrumb("", "event.messageDelete",
|
||||||
|
data: new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{"channel", evt.Channel.Id.ToString()},
|
||||||
|
{"guild", evt.Channel.Id.ToString()},
|
||||||
|
{"messages", string.Join(",", evt.Messages.Select(m => m.Id))},
|
||||||
|
});
|
||||||
|
scope.SetTag("shard", evt.Client.ShardId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enrich(Scope scope, MessageReactionAddEventArgs evt)
|
||||||
|
{
|
||||||
|
scope.AddBreadcrumb("", "event.reaction",
|
||||||
|
data: new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{"user", evt.User.Id.ToString()},
|
||||||
|
{"channel", (evt.Channel?.Id ?? 0).ToString()},
|
||||||
|
{"guild", (evt.Channel?.GuildId ?? 0).ToString()},
|
||||||
|
{"message", evt.Message.Id.ToString()},
|
||||||
|
{"reaction", evt.Emoji.Name}
|
||||||
|
});
|
||||||
|
scope.SetTag("shard", evt.Client.ShardId.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user