Fix API traces for weird endpoints

This commit is contained in:
Ske 2020-11-19 11:43:05 +01:00
parent feebbf657d
commit c60e6b21a4
2 changed files with 28 additions and 13 deletions

View File

@ -21,7 +21,7 @@ namespace PluralKit.Bot
public static TimerOptions WebhookResponseTime => new TimerOptions { Name = "Webhook Response Time", Context = "Bot", RateUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Seconds }; public static TimerOptions WebhookResponseTime => new TimerOptions { Name = "Webhook Response Time", Context = "Bot", RateUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Seconds };
public static TimerOptions MessageContextQueryTime => new TimerOptions { Name = "Message context query duration", Context = "Bot", RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Calls }; public static TimerOptions MessageContextQueryTime => new TimerOptions { Name = "Message context query duration", Context = "Bot", RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Calls };
public static TimerOptions ProxyMembersQueryTime => new TimerOptions { Name = "Proxy member query duration", Context = "Bot", RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Calls }; public static TimerOptions ProxyMembersQueryTime => new TimerOptions { Name = "Proxy member query duration", Context = "Bot", RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, MeasurementUnit = Unit.Calls };
public static TimerOptions DiscordApiRequests => new TimerOptions { Name = "Discord API requests", MeasurementUnit = Unit.Requests, Context = "Bot"}; public static TimerOptions DiscordApiRequests => new TimerOptions { Name = "Discord API requests", MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Milliseconds, Context = "Bot"};
public static MeterOptions BotErrors => new MeterOptions { Name = "Bot errors", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, Context = "Bot"}; public static MeterOptions BotErrors => new MeterOptions { Name = "Bot errors", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, Context = "Bot"};
public static MeterOptions ErrorMessagesSent => new MeterOptions { Name = "Error messages sent", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, Context = "Bot"}; public static MeterOptions ErrorMessagesSent => new MeterOptions { Name = "Error messages sent", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, Context = "Bot"};
public static TimerOptions EventsHandled => new TimerOptions { Name = "Events handled", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, Context = "Bot"}; public static TimerOptions EventsHandled => new TimerOptions { Name = "Events handled", MeasurementUnit = Unit.Errors, RateUnit = TimeUnit.Seconds, DurationUnit = TimeUnit.Seconds, Context = "Bot"};

View File

@ -52,28 +52,30 @@ namespace PluralKit.Bot
url = Regex.Replace(url, @"/reactions/[^{/]+/\d{17,19}", "/reactions/{emoji}/{user_id}"); url = Regex.Replace(url, @"/reactions/[^{/]+/\d{17,19}", "/reactions/{emoji}/{user_id}");
url = Regex.Replace(url, @"/reactions/[^{/]+", "/reactions/{emoji}"); url = Regex.Replace(url, @"/reactions/[^{/]+", "/reactions/{emoji}");
url = Regex.Replace(url, @"/invites/[^{/]+", "/invites/{invite_code}"); url = Regex.Replace(url, @"/invites/[^{/]+", "/invites/{invite_code}");
// catch-all for missed IDs
url = Regex.Replace(url, @"\d{17,19}", "{snowflake}");
return url; return url;
} }
private string Endpoint(HttpRequestMessage req) private string GetEndpointName(HttpRequestMessage req)
{ {
var routePath = NormalizeRoutePath(req.RequestUri.LocalPath.Replace("/api/v7", "")); var localPath = Regex.Replace(req.RequestUri.LocalPath, @"/api/v\d+", "");
var routePath = NormalizeRoutePath(localPath);
return $"{req.Method} {routePath}"; return $"{req.Method} {routePath}";
} }
private void HandleException(Exception exc, HttpRequestMessage req) private void HandleException(Exception exc, HttpRequestMessage req)
{ {
_logger _logger
.ForContext("RequestUrlRoute", Endpoint(req)) .ForContext("RequestUrlRoute", GetEndpointName(req))
.Error(exc, "HTTP error: {RequestMethod} {RequestUrl}", req.Method, req.RequestUri); .Error(exc, "HTTP error: {RequestMethod} {RequestUrl}", req.Method, req.RequestUri);
} }
private async Task HandleResponse(HttpResponseMessage response, Activity activity) private async Task HandleResponse(HttpResponseMessage response, Activity activity)
{ {
if (response.RequestMessage.RequestUri.Host != "discord.com") var endpoint = GetEndpointName(response.RequestMessage);
return;
var endpoint = Endpoint(response.RequestMessage);
using (LogContext.PushProperty("Elastic", "yes?")) using (LogContext.PushProperty("Elastic", "yes?"))
{ {
@ -100,12 +102,25 @@ namespace PluralKit.Bot
activity.Duration.TotalMilliseconds); activity.Duration.TotalMilliseconds);
} }
if (IsDiscordApiRequest(response))
{
var timer = _metrics.Provider.Timer.Instance(BotMetrics.DiscordApiRequests, new MetricTags( var timer = _metrics.Provider.Timer.Instance(BotMetrics.DiscordApiRequests, new MetricTags(
new[] {"endpoint", "status_code"}, new[] {"endpoint", "status_code"},
new[] {endpoint, ((int) response.StatusCode).ToString()} new[] {endpoint, ((int) response.StatusCode).ToString()}
)); ));
timer.Record(activity.Duration.Ticks / 10, TimeUnit.Microseconds); timer.Record(activity.Duration.Ticks / 10, TimeUnit.Microseconds);
} }
}
private static bool IsDiscordApiRequest(HttpResponseMessage response)
{
// Assume any properly authorized request is coming from D#+ and not some sort of user
var authHeader = response.RequestMessage.Headers.Authorization;
if (authHeader == null || authHeader.Scheme != "Bot")
return false;
return response.RequestMessage.RequestUri.AbsoluteUri.StartsWith("https://discord.com/api/");
}
public void OnNext(KeyValuePair<string, object> value) public void OnNext(KeyValuePair<string, object> value)
{ {