Refactor Sentry scope enrichment
This commit is contained in:
		| @@ -47,6 +47,8 @@ namespace PluralKit.Bot | ||||
|             _client.DebugLogger.LogMessageReceived += FrameworkLog; | ||||
|              | ||||
|             // 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.MessageDeleted += HandleEvent; | ||||
|             _client.MessageUpdated += HandleEvent; | ||||
| @@ -69,8 +71,14 @@ namespace PluralKit.Bot | ||||
|             async Task HandleEventInner() | ||||
|             { | ||||
|                 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>>(); | ||||
|  | ||||
|                  | ||||
|                 // 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 | ||||
|                 { | ||||
|                     await handler.Handle(evt); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| using App.Metrics; | ||||
| @@ -129,21 +128,6 @@ namespace PluralKit.Bot | ||||
|         { | ||||
|             _metrics.Measure.Meter.Mark(BotMetrics.MessagesReceived); | ||||
|             _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> | ||||
|     { | ||||
|         private readonly ProxyService _proxy; | ||||
|         private readonly Scope _sentryScope; | ||||
|  | ||||
|         public MessageDeleted(Scope sentryScope, ProxyService proxy) | ||||
|         public MessageDeleted(ProxyService proxy) | ||||
|         { | ||||
|             _sentryScope = sentryScope; | ||||
|             _proxy = proxy; | ||||
|         } | ||||
|          | ||||
|         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); | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -35,14 +35,6 @@ namespace PluralKit.Bot | ||||
|              | ||||
|             // Also, if this is in DMs don't bother either | ||||
|             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 (_lastMessageCache.GetLastMessage(evt.Channel.Id) != evt.Message.Id) return; | ||||
|   | ||||
| @@ -10,25 +10,14 @@ namespace PluralKit.Bot | ||||
|     public class ReactionAdded: IEventHandler<MessageReactionAddEventArgs> | ||||
|     { | ||||
|         private readonly ProxyService _proxy; | ||||
|         private readonly Scope _sentryScope; | ||||
|  | ||||
|         public ReactionAdded(ProxyService proxy, Scope sentryScope) | ||||
|         public ReactionAdded(ProxyService proxy) | ||||
|         { | ||||
|             _proxy = proxy; | ||||
|             _sentryScope = sentryScope; | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -69,6 +69,13 @@ namespace PluralKit.Bot | ||||
|              | ||||
|             // Sentry stuff | ||||
|             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 | ||||
|             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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user