Added metrics to Webhook API (total events, errors)

This commit is contained in:
Mia Rose Winter 2024-04-11 13:03:05 +02:00
parent a83fdbbe7a
commit a64e16f681
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
3 changed files with 41 additions and 3 deletions

View file

@ -4,16 +4,19 @@
using Microsoft.EntityFrameworkCore;
using Wave.Data;
using Wave.Data.Api.Mailtrap;
using Wave.Utilities.Metrics;
namespace Wave.Controllers;
[ApiController]
[Route("/api/[controller]")]
public class WebhookController(ILogger<WebhookController> logger, ApplicationDbContext context) : ControllerBase {
public class WebhookController(ILogger<WebhookController> logger, ApplicationDbContext context, ApiMetrics metrics)
: ControllerBase {
[HttpPost("mailtrap/{apiKey}")]
[Authorize("EmailApi", AuthenticationSchemes = "ApiKeyInRoute")]
public async Task<IActionResult> Mailtrap(Webhook webhook, string apiKey) {
foreach (var webhookEvent in webhook.Events) {
metrics.WebhookEventReceived("Mailtrap", webhookEvent.Type.ToString());
var subscriber = await context.Set<EmailSubscriber>().FirstOrDefaultAsync(s => s.Email == webhookEvent.Email);
logger.LogDebug("Received Webhook event {EventType} for {email}",
@ -24,6 +27,7 @@ public class WebhookController(ILogger<WebhookController> logger, ApplicationDbC
"Received webhook event from mailtrap of type {EventType}, " +
"but failed to find subscriber with E-Mail {email}.",
webhookEvent.Type, webhookEvent.Email);
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown email");
continue;
}
@ -59,6 +63,7 @@ public class WebhookController(ILogger<WebhookController> logger, ApplicationDbC
case WebhookEventType.Click:
default:
logger.LogInformation("Received unsupported event {EventType} for {email}. Skipping.", webhookEvent.Type, webhookEvent.Email);
metrics.WebhookEventError("Mailtrap", webhookEvent.Type.ToString(), "unknown type");
return Ok();
}

View file

@ -26,6 +26,7 @@
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Grafana.Loki;
using Wave.Utilities.Metrics;
#region Version Information
@ -275,7 +276,7 @@
#endregion
#region Open Telemetry
#region Open Telemetry & Metrics
var features = builder.Configuration.GetSection(nameof(Features)).Get<Features>();
if (features?.Telemetry is true) {
@ -292,7 +293,7 @@
.AddMeter("Microsoft.AspNetCore.Http.Connections")
.AddMeter("Microsoft.AspNetCore.Http.Routing")
.AddMeter("Microsoft.AspNetCore.Diagnostics")
.AddMeter("Wave.Api")
.AddPrometheusExporter());
// Jaeger etc.
@ -303,6 +304,8 @@
tracing.AddOtlpExporter(options => options.Endpoint = new Uri(otlpUrl));
});
}
builder.Services.AddSingleton<ApiMetrics>();
}
#endregion

View file

@ -0,0 +1,30 @@
using System.Diagnostics.Metrics;
namespace Wave.Utilities.Metrics;
public class ApiMetrics {
private Counter<int> WebhookEventCounter { get; }
private Counter<int> WebhookErrorCounter { get; }
public ApiMetrics(IMeterFactory meterFactory) {
var meter = meterFactory.Create("Wave.Api");
WebhookEventCounter = meter.CreateCounter<int>("wave.webhook.events", "{events}",
description: "Counts the incoming webhook events");
WebhookErrorCounter = meter.CreateCounter<int>("wave.webhook.errors", "{events}",
description: "Counts errors in webhook events");
}
public void WebhookEventReceived(string api, string type) {
WebhookEventCounter.Add(1,
new KeyValuePair<string, object?>("wave.webhook.event_type", type),
new KeyValuePair<string, object?>("wave.webhook.api", api));
}
public void WebhookEventError(string api, string type, string reason) {
WebhookErrorCounter.Add(1,
new KeyValuePair<string, object?>("wave.webhook.event_type", type),
new KeyValuePair<string, object?>("wave.webhook.api", api),
new KeyValuePair<string, object?>("wave.error.reason", reason));
}
}