Updates to Elastic logging
This commit is contained in:
parent
ae9ed0f4ee
commit
ae82bb4168
@ -21,7 +21,7 @@ namespace Myriad.Gateway
|
|||||||
public Cluster(GatewaySettings gatewaySettings, ILogger logger)
|
public Cluster(GatewaySettings gatewaySettings, ILogger logger)
|
||||||
{
|
{
|
||||||
_gatewaySettings = gatewaySettings;
|
_gatewaySettings = gatewaySettings;
|
||||||
_logger = logger;
|
_logger = logger.ForContext<Cluster>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<Shard, IGatewayEvent, Task>? EventReceived { get; set; }
|
public Func<Shard, IGatewayEvent, Task>? EventReceived { get; set; }
|
||||||
|
@ -56,7 +56,7 @@ namespace Myriad.Gateway.Limit
|
|||||||
if (!queue.TryDequeue(out var tcs))
|
if (!queue.TryDequeue(out var tcs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_logger.Information(
|
_logger.Debug(
|
||||||
"Allowing identify for bucket {BucketId} through ({QueueLength} left in bucket queue)",
|
"Allowing identify for bucket {BucketId} through ({QueueLength} left in bucket queue)",
|
||||||
bucket, queue.Count);
|
bucket, queue.Count);
|
||||||
tcs.SetResult();
|
tcs.SetResult();
|
||||||
|
@ -14,7 +14,7 @@ namespace Myriad.Gateway.Limit
|
|||||||
public TwilightGatewayRatelimiter(ILogger logger, string url)
|
public TwilightGatewayRatelimiter(ILogger logger, string url)
|
||||||
{
|
{
|
||||||
_url = url;
|
_url = url;
|
||||||
_logger = logger;
|
_logger = logger.ForContext<TwilightGatewayRatelimiter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Identify(int shard)
|
public async Task Identify(int shard)
|
||||||
|
@ -9,6 +9,7 @@ using Myriad.Serialization;
|
|||||||
using Myriad.Types;
|
using Myriad.Types;
|
||||||
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Serilog.Context;
|
||||||
|
|
||||||
namespace Myriad.Gateway
|
namespace Myriad.Gateway
|
||||||
{
|
{
|
||||||
@ -50,7 +51,7 @@ namespace Myriad.Gateway
|
|||||||
_info = info;
|
_info = info;
|
||||||
_ratelimiter = ratelimiter;
|
_ratelimiter = ratelimiter;
|
||||||
_url = url;
|
_url = url;
|
||||||
_logger = logger;
|
_logger = logger.ForContext<Shard>().ForContext("ShardId", info.ShardId);
|
||||||
_stateManager = new ShardStateManager(info, _jsonSerializerOptions, logger)
|
_stateManager = new ShardStateManager(info, _jsonSerializerOptions, logger)
|
||||||
{
|
{
|
||||||
HandleEvent = HandleEvent,
|
HandleEvent = HandleEvent,
|
||||||
@ -70,6 +71,9 @@ namespace Myriad.Gateway
|
|||||||
|
|
||||||
private async Task ShardLoop()
|
private async Task ShardLoop()
|
||||||
{
|
{
|
||||||
|
// may be superfluous but this adds shard id to ambient context which is nice
|
||||||
|
using var _ = LogContext.PushProperty("ShardId", _info.ShardId);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -140,8 +140,8 @@ namespace Myriad.Gateway
|
|||||||
_hasReceivedHeartbeatAck = true;
|
_hasReceivedHeartbeatAck = true;
|
||||||
_latency = DateTimeOffset.UtcNow - _lastHeartbeatSent;
|
_latency = DateTimeOffset.UtcNow - _lastHeartbeatSent;
|
||||||
OnHeartbeatReceived?.Invoke(_latency!.Value);
|
OnHeartbeatReceived?.Invoke(_latency!.Value);
|
||||||
_logger.Information("Shard {ShardId}: Received Heartbeat (latency {Latency} ms)",
|
_logger.Debug("Shard {ShardId}: Received Heartbeat (latency {Latency:N2} ms)",
|
||||||
_info.ShardId, _latency);
|
_info.ShardId, _latency?.TotalMilliseconds);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ using Myriad.Serialization;
|
|||||||
using Polly;
|
using Polly;
|
||||||
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Serilog.Context;
|
||||||
|
|
||||||
namespace Myriad.Rest
|
namespace Myriad.Rest
|
||||||
{
|
{
|
||||||
@ -172,8 +173,10 @@ namespace Myriad.Rest
|
|||||||
{
|
{
|
||||||
return await _retryPolicy.ExecuteAsync(async _ =>
|
return await _retryPolicy.ExecuteAsync(async _ =>
|
||||||
{
|
{
|
||||||
|
using var __ = LogContext.PushProperty("EndpointName", ratelimitParams.endpointName);
|
||||||
|
|
||||||
var request = createRequest();
|
var request = createRequest();
|
||||||
_logger.Debug("Sending request: {RequestMethod} {RequestPath}",
|
_logger.Debug("Request: {RequestMethod} {RequestPath}",
|
||||||
request.Method, request.RequestUri);
|
request.Method, request.RequestUri);
|
||||||
|
|
||||||
request.Version = _httpVersion;
|
request.Version = _httpVersion;
|
||||||
@ -185,9 +188,8 @@ namespace Myriad.Rest
|
|||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
"Received response in {ResponseDurationMs} ms: {RequestMethod} {RequestPath} -> {StatusCode} {ReasonPhrase}",
|
"Response: {RequestMethod} {RequestPath} -> {StatusCode} {ReasonPhrase} (in {ResponseDurationMs} ms)",
|
||||||
stopwatch.ElapsedMilliseconds, request.Method, request.RequestUri, (int) response.StatusCode,
|
request.Method, request.RequestUri, (int) response.StatusCode, response.ReasonPhrase, stopwatch.ElapsedMilliseconds);
|
||||||
response.ReasonPhrase);
|
|
||||||
|
|
||||||
await HandleApiError(response, ignoreNotFound);
|
await HandleApiError(response, ignoreNotFound);
|
||||||
|
|
||||||
@ -208,14 +210,16 @@ namespace Myriad.Rest
|
|||||||
if (response.StatusCode == HttpStatusCode.NotFound && ignoreNotFound)
|
if (response.StatusCode == HttpStatusCode.NotFound && ignoreNotFound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
throw await CreateDiscordException(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ValueTask<DiscordRequestException> CreateDiscordException(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
var body = await response.Content.ReadAsStringAsync();
|
var body = await response.Content.ReadAsStringAsync();
|
||||||
var apiError = TryParseApiError(body);
|
var apiError = TryParseApiError(body);
|
||||||
|
if (apiError != null)
|
||||||
|
_logger.Warning("Discord API error: {DiscordErrorCode} {DiscordErrorMessage}", apiError.Code, apiError.Message);
|
||||||
|
|
||||||
|
throw CreateDiscordException(response, body, apiError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiscordRequestException CreateDiscordException(HttpResponseMessage response, string body, DiscordApiError? apiError)
|
||||||
|
{
|
||||||
return response.StatusCode switch
|
return response.StatusCode switch
|
||||||
{
|
{
|
||||||
HttpStatusCode.BadRequest => new BadRequestException(response, body, apiError),
|
HttpStatusCode.BadRequest => new BadRequestException(response, body, apiError),
|
||||||
|
@ -50,7 +50,7 @@ namespace Myriad.Rest.Ratelimit
|
|||||||
|
|
||||||
if (Remaining > 0)
|
if (Remaining > 0)
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Verbose(
|
||||||
"{BucketKey}/{BucketMajor}: Bucket has [{BucketRemaining}/{BucketLimit} left], allowing through",
|
"{BucketKey}/{BucketMajor}: Bucket has [{BucketRemaining}/{BucketLimit} left], allowing through",
|
||||||
Key, Major, Remaining, Limit);
|
Key, Major, Remaining, Limit);
|
||||||
Remaining--;
|
Remaining--;
|
||||||
@ -82,7 +82,7 @@ namespace Myriad.Rest.Ratelimit
|
|||||||
var headerNextReset = DateTimeOffset.UtcNow + headers.ResetAfter.Value; // todo: server time
|
var headerNextReset = DateTimeOffset.UtcNow + headers.ResetAfter.Value; // todo: server time
|
||||||
if (_nextReset == null || headerNextReset > _nextReset)
|
if (_nextReset == null || headerNextReset > _nextReset)
|
||||||
{
|
{
|
||||||
_logger.Debug("{BucketKey}/{BucketMajor}: Received reset time {NextReset} from server (after: {NextResetAfter}, remaining: {Remaining}, local remaining: {LocalRemaining})",
|
_logger.Verbose("{BucketKey}/{BucketMajor}: Received reset time {NextReset} from server (after: {NextResetAfter}, remaining: {Remaining}, local remaining: {LocalRemaining})",
|
||||||
Key, Major, headerNextReset, headers.ResetAfter.Value, headers.Remaining, Remaining);
|
Key, Major, headerNextReset, headers.ResetAfter.Value, headers.Remaining, Remaining);
|
||||||
|
|
||||||
_nextReset = headerNextReset;
|
_nextReset = headerNextReset;
|
||||||
|
@ -177,13 +177,12 @@ namespace PluralKit.Bot
|
|||||||
{
|
{
|
||||||
await Task.Yield();
|
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();
|
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
|
// 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>>();
|
var sentryEnricher = serviceScope.ResolveOptional<ISentryEnricher<T>>();
|
||||||
sentryEnricher?.Enrich(serviceScope.Resolve<Scope>(), shard, evt);
|
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
|
// Make this beforehand so we can access the event ID for logging
|
||||||
var sentryEvent = new SentryEvent(exc);
|
var sentryEvent = new SentryEvent(exc);
|
||||||
|
|
||||||
_logger
|
_logger.Error(exc, "Exception in event handler: {SentryEventId}", sentryEvent.EventId);
|
||||||
.ForContext("Elastic", "yes?")
|
|
||||||
.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 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)
|
if (evt is MessageCreateEvent mc && mc.Author.Id == shard.User?.Id)
|
||||||
|
@ -116,6 +116,7 @@ namespace PluralKit.Bot
|
|||||||
Timeout = TimeSpan.FromSeconds(5)
|
Timeout = TimeSpan.FromSeconds(5)
|
||||||
}).AsSelf().SingleInstance();
|
}).AsSelf().SingleInstance();
|
||||||
builder.RegisterInstance(SystemClock.Instance).As<IClock>();
|
builder.RegisterInstance(SystemClock.Instance).As<IClock>();
|
||||||
|
builder.RegisterType<SerilogGatewayEnricherFactory>().AsSelf().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterType<DiscordRequestObserver>().AsSelf().SingleInstance();
|
builder.RegisterType<DiscordRequestObserver>().AsSelf().SingleInstance();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace PluralKit.Bot
|
|||||||
_db = db;
|
_db = db;
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_clock = clock;
|
_clock = clock;
|
||||||
_logger = logger;
|
_logger = logger.ForContext<CommandMessageService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RegisterMessage(ulong messageId, ulong authorId)
|
public async Task RegisterMessage(ulong messageId, ulong authorId)
|
||||||
|
@ -71,7 +71,7 @@ namespace PluralKit.Bot
|
|||||||
public async Task<Webhook> InvalidateAndRefreshWebhook(ulong channelId, Webhook webhook)
|
public async Task<Webhook> InvalidateAndRefreshWebhook(ulong channelId, Webhook webhook)
|
||||||
{
|
{
|
||||||
// note: webhook.ChannelId may not be the same as channelId >.>
|
// 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 _);
|
_webhooks.TryRemove(webhook.ChannelId, out _);
|
||||||
return await GetWebhook(channelId);
|
return await GetWebhook(channelId);
|
||||||
|
@ -16,6 +16,7 @@ using Serilog.Context;
|
|||||||
|
|
||||||
namespace PluralKit.Bot
|
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>>
|
public class DiscordRequestObserver: IObserver<KeyValuePair<string, object>>
|
||||||
{
|
{
|
||||||
private readonly IMetrics _metrics;
|
private readonly IMetrics _metrics;
|
||||||
@ -77,6 +78,8 @@ namespace PluralKit.Bot
|
|||||||
{
|
{
|
||||||
var endpoint = GetEndpointName(response.RequestMessage);
|
var endpoint = GetEndpointName(response.RequestMessage);
|
||||||
|
|
||||||
|
// (see phase-out notice at top of file)
|
||||||
|
/*
|
||||||
using (LogContext.PushProperty("Elastic", "yes?"))
|
using (LogContext.PushProperty("Elastic", "yes?"))
|
||||||
{
|
{
|
||||||
if ((int) response.StatusCode >= 400)
|
if ((int) response.StatusCode >= 400)
|
||||||
@ -101,6 +104,7 @@ namespace PluralKit.Bot
|
|||||||
response.ReasonPhrase,
|
response.ReasonPhrase,
|
||||||
activity.Duration.TotalMilliseconds);
|
activity.Duration.TotalMilliseconds);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (IsDiscordApiRequest(response))
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,10 @@ namespace PluralKit.Core
|
|||||||
public string InfluxUrl { get; set; }
|
public string InfluxUrl { get; set; }
|
||||||
public string InfluxDb { get; set; }
|
public string InfluxDb { get; set; }
|
||||||
public string LogDir { get; set; }
|
public string LogDir { get; set; }
|
||||||
public string ElasticUrl { get; set; }
|
public string? ElasticUrl { get; set; }
|
||||||
|
|
||||||
public LogEventLevel ConsoleLogLevel { get; set; } = LogEventLevel.Debug;
|
public LogEventLevel ConsoleLogLevel { get; set; } = LogEventLevel.Debug;
|
||||||
|
public LogEventLevel ElasticLogLevel { get; set; } = LogEventLevel.Information;
|
||||||
public LogEventLevel FileLogLevel { get; set; } = LogEventLevel.Information;
|
public LogEventLevel FileLogLevel { get; set; } = LogEventLevel.Information;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ namespace PluralKit.Core
|
|||||||
_config = config;
|
_config = config;
|
||||||
_countHolder = countHolder;
|
_countHolder = countHolder;
|
||||||
_metrics = metrics;
|
_metrics = metrics;
|
||||||
_logger = logger;
|
_logger = logger.ForContext<Database>();
|
||||||
|
|
||||||
_connectionString = new NpgsqlConnectionStringBuilder(_config.Database)
|
_connectionString = new NpgsqlConnectionStringBuilder(_config.Database)
|
||||||
{
|
{
|
||||||
|
@ -8,8 +8,7 @@ namespace PluralKit.Core
|
|||||||
|
|
||||||
public ModelRepository(ILogger logger)
|
public ModelRepository(ILogger logger)
|
||||||
{
|
{
|
||||||
_logger = logger.ForContext<ILogger>()
|
_logger = logger.ForContext<ModelRepository>();
|
||||||
.ForContext("Elastic", "yes?");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,7 +52,6 @@ namespace PluralKit.Core
|
|||||||
|
|
||||||
// Don't want App.Metrics/D#+ spam
|
// Don't want App.Metrics/D#+ spam
|
||||||
.MinimumLevel.Override("App.Metrics", LogEventLevel.Information)
|
.MinimumLevel.Override("App.Metrics", LogEventLevel.Information)
|
||||||
.MinimumLevel.Override("DSharpPlus", LogEventLevel.Debug)
|
|
||||||
|
|
||||||
// Actual formatting for these is handled in ScalarFormatting
|
// Actual formatting for these is handled in ScalarFormatting
|
||||||
.Destructure.AsScalar<SystemId>()
|
.Destructure.AsScalar<SystemId>()
|
||||||
@ -98,14 +97,12 @@ namespace PluralKit.Core
|
|||||||
{
|
{
|
||||||
AutoRegisterTemplate = true,
|
AutoRegisterTemplate = true,
|
||||||
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
|
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
|
||||||
MinimumLogEventLevel = LogEventLevel.Verbose,
|
MinimumLogEventLevel = config.ElasticLogLevel,
|
||||||
IndexFormat = "pluralkit-logs-{0:yyyy.MM.dd}",
|
IndexFormat = "pluralkit-logs-{0:yyyy.MM.dd}",
|
||||||
CustomFormatter = new ScalarFormatting.Elasticsearch()
|
CustomFormatter = new ScalarFormatting.Elasticsearch(),
|
||||||
};
|
};
|
||||||
|
|
||||||
logCfg.WriteTo
|
logCfg.WriteTo.Elasticsearch(elasticConfig);
|
||||||
.Conditional(e => e.Properties.ContainsKey("Elastic"),
|
|
||||||
c => c.Elasticsearch(elasticConfig));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_fn.Invoke(logCfg);
|
_fn.Invoke(logCfg);
|
||||||
|
Loading…
Reference in New Issue
Block a user