feat(scadabridge): emit scadabridge.inbound_api.requests (by method) at inbound API entry

This commit is contained in:
Joseph Doherty
2026-06-01 17:03:10 -04:00
parent 547b685a42
commit 782fb73015
2 changed files with 127 additions and 0 deletions
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.ScadaBridge.Commons.Observability;
using ZB.MOM.WW.ScadaBridge.InboundAPI.Middleware;
namespace ZB.MOM.WW.ScadaBridge.InboundAPI;
@@ -44,6 +45,16 @@ public static class EndpointExtensions
if (!validationResult.IsValid)
{
// Telemetry follow-on: count every inbound request, including auth
// failures. The raw {methodName} route value is arbitrary caller input
// and would be high-cardinality, so failures are tagged with a small
// bounded set of sentinels keyed off the validator's status code rather
// than the unvalidated name (401 → "<unauthorized>", 403 → "<forbidden>").
ScadaBridgeTelemetry.RecordInboundApiRequest(
validationResult.StatusCode == StatusCodes.Status401Unauthorized
? "<unauthorized>"
: "<forbidden>");
// WP-5: Failures-only logging
logger.LogWarning(
"Inbound API auth failure for method {Method}: {Error} (status {StatusCode})",
@@ -56,6 +67,12 @@ public static class EndpointExtensions
var method = validationResult.Method!;
// Telemetry follow-on: count this inbound request against the resolved,
// registered method name. method.Name comes from the repository's method
// catalogue (an exact-name lookup), so the `method` tag is bounded to the
// set of configured API methods — never the raw caller-supplied route value.
ScadaBridgeTelemetry.RecordInboundApiRequest(method.Name);
// Audit Log (#23 M4 Bundle D): publish the resolved API key name so
// AuditWriteMiddleware can populate AuditEvent.Actor in its finally
// block. Done AFTER validation succeeded — auth failures leave the