Updates to Elastic logging
This commit is contained in:
@@ -176,14 +176,13 @@ namespace PluralKit.Bot
|
||||
async Task HandleEventInner()
|
||||
{
|
||||
await Task.Yield();
|
||||
|
||||
using var _ = LogContext.PushProperty("EventId", Guid.NewGuid());
|
||||
_logger
|
||||
.ForContext("Elastic", "yes?")
|
||||
.Verbose("Gateway event: {@Event}", evt);
|
||||
|
||||
|
||||
await using var serviceScope = _services.BeginLifetimeScope();
|
||||
|
||||
using var _ = LogContext.PushProperty("EventId", Guid.NewGuid());
|
||||
using var __ = LogContext.Push(serviceScope.Resolve<SerilogGatewayEnricherFactory>().GetEnricher(shard, evt));
|
||||
_logger.Verbose("Received gateway event: {@Event}", evt);
|
||||
|
||||
// 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>(), shard, evt);
|
||||
@@ -218,9 +217,7 @@ namespace PluralKit.Bot
|
||||
// Make this beforehand so we can access the event ID for logging
|
||||
var sentryEvent = new SentryEvent(exc);
|
||||
|
||||
_logger
|
||||
.ForContext("Elastic", "yes?")
|
||||
.Error(exc, "Exception in event handler: {SentryEventId}", sentryEvent.EventId);
|
||||
_logger.Error(exc, "Exception in event handler: {SentryEventId}", sentryEvent.EventId);
|
||||
|
||||
// If the event is us responding to our own error messages, don't bother logging
|
||||
if (evt is MessageCreateEvent mc && mc.Author.Id == shard.User?.Id)
|
||||
|
||||
@@ -116,6 +116,7 @@ namespace PluralKit.Bot
|
||||
Timeout = TimeSpan.FromSeconds(5)
|
||||
}).AsSelf().SingleInstance();
|
||||
builder.RegisterInstance(SystemClock.Instance).As<IClock>();
|
||||
builder.RegisterType<SerilogGatewayEnricherFactory>().AsSelf().SingleInstance();
|
||||
|
||||
builder.RegisterType<DiscordRequestObserver>().AsSelf().SingleInstance();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace PluralKit.Bot
|
||||
_db = db;
|
||||
_repo = repo;
|
||||
_clock = clock;
|
||||
_logger = logger;
|
||||
_logger = logger.ForContext<CommandMessageService>();
|
||||
}
|
||||
|
||||
public async Task RegisterMessage(ulong messageId, ulong authorId)
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace PluralKit.Bot
|
||||
public async Task<Webhook> InvalidateAndRefreshWebhook(ulong channelId, Webhook webhook)
|
||||
{
|
||||
// note: webhook.ChannelId may not be the same as channelId >.>
|
||||
_logger.Information("Refreshing webhook for channel {Channel}", webhook.ChannelId);
|
||||
_logger.Debug("Refreshing webhook for channel {Channel}", webhook.ChannelId);
|
||||
|
||||
_webhooks.TryRemove(webhook.ChannelId, out _);
|
||||
return await GetWebhook(channelId);
|
||||
|
||||
@@ -16,6 +16,7 @@ using Serilog.Context;
|
||||
|
||||
namespace PluralKit.Bot
|
||||
{
|
||||
// TODO: phase this out; it currently still handles metrics but that needs to be moved to Myriad probably?
|
||||
public class DiscordRequestObserver: IObserver<KeyValuePair<string, object>>
|
||||
{
|
||||
private readonly IMetrics _metrics;
|
||||
@@ -77,6 +78,8 @@ namespace PluralKit.Bot
|
||||
{
|
||||
var endpoint = GetEndpointName(response.RequestMessage);
|
||||
|
||||
// (see phase-out notice at top of file)
|
||||
/*
|
||||
using (LogContext.PushProperty("Elastic", "yes?"))
|
||||
{
|
||||
if ((int) response.StatusCode >= 400)
|
||||
@@ -101,6 +104,7 @@ namespace PluralKit.Bot
|
||||
response.ReasonPhrase,
|
||||
activity.Duration.TotalMilliseconds);
|
||||
}
|
||||
*/
|
||||
|
||||
if (IsDiscordApiRequest(response))
|
||||
{
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Myriad.Gateway;
|
||||
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace PluralKit.Bot
|
||||
{
|
||||
// This class is unused and commented out in Init.cs - it's here from before the lib conversion. Is it needed??
|
||||
public class EventDestructuring: IDestructuringPolicy
|
||||
{
|
||||
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory,
|
||||
out LogEventPropertyValue result)
|
||||
{
|
||||
if (!(value is IGatewayEvent evt))
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var props = new List<LogEventProperty>
|
||||
{
|
||||
new("Type", new ScalarValue(evt.EventType())),
|
||||
};
|
||||
|
||||
void AddMessage(ulong id, ulong channelId, ulong? guildId, ulong? author)
|
||||
{
|
||||
props.Add(new LogEventProperty("MessageId", new ScalarValue(id)));
|
||||
props.Add(new LogEventProperty("ChannelId", new ScalarValue(channelId)));
|
||||
props.Add(new LogEventProperty("GuildId", new ScalarValue(guildId ?? 0)));
|
||||
|
||||
if (author != null)
|
||||
props.Add(new LogEventProperty("AuthorId", new ScalarValue(author)));
|
||||
}
|
||||
|
||||
if (value is MessageCreateEvent mc)
|
||||
AddMessage(mc.Id, mc.ChannelId, mc.GuildId, mc.Author.Id);
|
||||
else if (value is MessageUpdateEvent mu)
|
||||
AddMessage(mu.Id, mu.ChannelId, mu.GuildId.Value, mu.Author.Value?.Id);
|
||||
else if (value is MessageDeleteEvent md)
|
||||
AddMessage(md.Id, md.ChannelId, md.GuildId, null);
|
||||
else if (value is MessageReactionAddEvent mra)
|
||||
{
|
||||
AddMessage(mra.MessageId, mra.ChannelId, mra.GuildId, null);
|
||||
props.Add(new LogEventProperty("ReactingUserId", new ScalarValue(mra.Emoji)));
|
||||
props.Add(new LogEventProperty("Emoji", new ScalarValue(mra.Emoji.Name)));
|
||||
}
|
||||
|
||||
// Want shard last, just for visual reasons
|
||||
// TODO: D#+ update means we can't pull shard ID out of this, what do?
|
||||
// props.Add(new LogEventProperty("Shard", new ScalarValue(dea.Client.ShardId)));
|
||||
|
||||
result = new StructureValue(props);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
104
PluralKit.Bot/Utils/SerilogGatewayEnricherFactory.cs
Normal file
104
PluralKit.Bot/Utils/SerilogGatewayEnricherFactory.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Myriad.Cache;
|
||||
using Myriad.Extensions;
|
||||
using Myriad.Gateway;
|
||||
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace PluralKit.Bot
|
||||
{
|
||||
public class SerilogGatewayEnricherFactory
|
||||
{
|
||||
private readonly Bot _bot;
|
||||
private readonly IDiscordCache _cache;
|
||||
|
||||
public SerilogGatewayEnricherFactory(Bot bot, IDiscordCache cache)
|
||||
{
|
||||
_bot = bot;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public ILogEventEnricher GetEnricher(Shard shard, IGatewayEvent evt)
|
||||
{
|
||||
var props = new List<LogEventProperty>
|
||||
{
|
||||
new("ShardId", new ScalarValue(shard.ShardId)),
|
||||
};
|
||||
|
||||
var (guild, channel) = GetGuildChannelId(evt);
|
||||
var user = GetUserId(evt);
|
||||
var message = GetMessageId(evt);
|
||||
|
||||
if (guild != null)
|
||||
props.Add(new("GuildId", new ScalarValue(guild.Value)));
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
props.Add(new("GuildId", new ScalarValue(channel.Value)));
|
||||
|
||||
var botPermissions = _bot.PermissionsIn(channel.Value);
|
||||
props.Add(new("BotPermissions", new ScalarValue(botPermissions)));
|
||||
}
|
||||
|
||||
if (message != null)
|
||||
props.Add(new("MessageId", new ScalarValue(message.Value)));
|
||||
|
||||
if (user != null)
|
||||
props.Add(new("UserId", new ScalarValue(user.Value)));
|
||||
|
||||
if (evt is MessageCreateEvent mce)
|
||||
props.Add(new("UserPermissions", new ScalarValue(_cache.PermissionsFor(mce))));
|
||||
|
||||
return new Inner(props);
|
||||
}
|
||||
|
||||
private (ulong?, ulong?) GetGuildChannelId(IGatewayEvent evt) => evt switch
|
||||
{
|
||||
ChannelCreateEvent e => (e.GuildId, e.Id),
|
||||
ChannelUpdateEvent e => (e.GuildId, e.Id),
|
||||
ChannelDeleteEvent e => (e.GuildId, e.Id),
|
||||
MessageCreateEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageUpdateEvent e => (e.GuildId.Value, e.ChannelId),
|
||||
MessageDeleteEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageDeleteBulkEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageReactionAddEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageReactionRemoveEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageReactionRemoveAllEvent e => (e.GuildId, e.ChannelId),
|
||||
MessageReactionRemoveEmojiEvent e => (e.GuildId, e.ChannelId),
|
||||
InteractionCreateEvent e => (e.GuildId, e.ChannelId),
|
||||
_ => (null, null)
|
||||
};
|
||||
|
||||
private ulong? GetUserId(IGatewayEvent evt) => evt switch
|
||||
{
|
||||
MessageCreateEvent e => e.Author.Id,
|
||||
MessageUpdateEvent e => e.Author.HasValue ? e.Author.Value.Id : null,
|
||||
MessageReactionAddEvent e => e.UserId,
|
||||
MessageReactionRemoveEvent e => e.UserId,
|
||||
InteractionCreateEvent e => e.Member?.User?.Id // todo: these nullable?
|
||||
};
|
||||
|
||||
private ulong? GetMessageId(IGatewayEvent evt) => evt switch
|
||||
{
|
||||
MessageCreateEvent e => e.Id,
|
||||
MessageUpdateEvent e => e.Id,
|
||||
MessageDeleteEvent e => e.Id,
|
||||
MessageReactionAddEvent e => e.MessageId,
|
||||
MessageReactionRemoveEvent e => e.MessageId,
|
||||
MessageReactionRemoveAllEvent e => e.MessageId,
|
||||
MessageReactionRemoveEmojiEvent e => e.MessageId,
|
||||
InteractionCreateEvent e => e.Message?.Id,
|
||||
};
|
||||
|
||||
private record Inner(List<LogEventProperty> Properties): ILogEventEnricher
|
||||
{
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
foreach (var prop in Properties)
|
||||
logEvent.AddPropertyIfAbsent(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user