diff --git a/services/bff/Bff.Api/Bff.Api.csproj b/services/bff/Bff.Api/Bff.Api.csproj index cb4f665..1187014 100644 --- a/services/bff/Bff.Api/Bff.Api.csproj +++ b/services/bff/Bff.Api/Bff.Api.csproj @@ -11,6 +11,7 @@ + diff --git a/services/bff/Bff.Api/Program.cs b/services/bff/Bff.Api/Program.cs index dcadd14..45e6d13 100644 --- a/services/bff/Bff.Api/Program.cs +++ b/services/bff/Bff.Api/Program.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Bff.Api; using Microsoft.AspNetCore.Authentication.JwtBearer; +using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; @@ -18,7 +19,16 @@ builder.Services.AddOpenTelemetry() .WithTracing(tracing => tracing .AddAspNetCoreInstrumentation(o => o.Filter = ctx => ctx.Request.Path != "/health") .AddHttpClientInstrumentation() - .AddOtlpExporter()); + .AddOtlpExporter()) + // OpenTelemetry metrics (S-16c, ADR-0023): the golden signals for the request path — + // http.server.request.duration (traffic/errors/latency) + http.client.* for the downstream hops, + // plus the built-in System.Runtime meter for saturation (GC, CPU, thread pool). Prometheus scrapes + // these from /metrics (mapped below); no OTLP push for metrics, so no collector hop (ADR-0023). + .WithMetrics(metrics => metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddMeter("System.Runtime") + .AddPrometheusExporter()); var keycloakAuthority = builder.Configuration["Keycloak:Authority"] ?? throw new InvalidOperationException("Missing configuration 'Keycloak:Authority'"); @@ -82,6 +92,9 @@ app.UseAuthentication(); app.UseAuthorization(); app.MapHealthChecks("/health"); + +// Prometheus scrape endpoint (S-16c): exposes the OTel metrics above in Prometheus text format. +app.MapPrometheusScrapingEndpoint(); app.MapOpenApi(); // Self-service submit: requires a valid digid token; the bsn comes from the token, not the body,