feat(obs): golden-signal metrics on /metrics + Prometheus scrape + Grafana dashboard (S-16c, refs #124)
CI / lint (pull_request) Successful in 5m7s
CI / unit (pull_request) Successful in 2m2s
CI / frontend (pull_request) Successful in 3m58s
CI / mutation (pull_request) Successful in 6m30s
CI / verify-stack (pull_request) Successful in 9m34s
CI / build (pull_request) Successful in 4m57s
CI / lint (pull_request) Successful in 5m7s
CI / unit (pull_request) Successful in 2m2s
CI / frontend (pull_request) Successful in 3m58s
CI / mutation (pull_request) Successful in 6m30s
CI / verify-stack (pull_request) Successful in 9m34s
CI / build (pull_request) Successful in 4m57s
Wire OTel metrics into the four remaining .NET services (acl, domain, event-subscriber, projection-api) exactly as the BFF: ASP.NET Core + HttpClient instrumentation + the built-in System.Runtime meter, exposed at /metrics via the Prometheus AspNetCore exporter (ADR-0024). Prometheus scrapes one job per service; Grafana ships a pre-built 'Request path — golden signals' dashboard (traffic/errors/latency/saturation). A verify-metrics CI step proves the endpoints are scraped end to end.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.17.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.17.0" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Acl.Application;
|
||||
using Acl.Infrastructure;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
@@ -14,7 +15,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): golden signals for the request path —
|
||||
// http.server.request.duration (traffic/errors/latency) + http.client.* for downstream hops, plus
|
||||
// the built-in System.Runtime meter for saturation (GC, CPU, thread pool). Prometheus scrapes these
|
||||
// from /metrics (mapped below); metrics aren't pushed over OTLP, so no collector hop (ADR-0023).
|
||||
.WithMetrics(metrics => metrics
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddMeter("System.Runtime")
|
||||
.AddPrometheusExporter());
|
||||
|
||||
builder.Services.AddSingleton<IClock, SystemClock>();
|
||||
builder.Services.AddSingleton(sp => sp.GetRequiredService<IConfiguration>()
|
||||
@@ -32,6 +42,9 @@ var app = builder.Build();
|
||||
|
||||
app.MapGet("/health", () => "Healthy");
|
||||
|
||||
// Prometheus scrape endpoint (S-16c): exposes the OTel metrics above in Prometheus text format.
|
||||
app.MapPrometheusScrapingEndpoint();
|
||||
|
||||
// The ACL's single operation, exposed as a service endpoint.
|
||||
app.MapPost("/zaken", async (OpenZaakRequest body, AclService acl, CancellationToken ct) =>
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.17.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.17.0" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Big.Application;
|
||||
using Big.Domain;
|
||||
using Big.Infrastructure;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Quartz;
|
||||
@@ -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): golden signals for the request path —
|
||||
// http.server.request.duration (traffic/errors/latency) + http.client.* for downstream hops, plus
|
||||
// the built-in System.Runtime meter for saturation (GC, CPU, thread pool). Prometheus scrapes these
|
||||
// from /metrics (mapped below); metrics aren't pushed over OTLP, so no collector hop (ADR-0023).
|
||||
.WithMetrics(metrics => metrics
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddMeter("System.Runtime")
|
||||
.AddPrometheusExporter());
|
||||
|
||||
// Options bound from configuration (compose sets Flowable__* and Acl__* env vars).
|
||||
builder.Services.AddSingleton(sp => sp.GetRequiredService<IConfiguration>()
|
||||
@@ -84,6 +94,9 @@ var app = builder.Build();
|
||||
|
||||
app.MapGet("/health", () => "Healthy");
|
||||
|
||||
// Prometheus scrape endpoint (S-16c): exposes the OTel metrics above in Prometheus text format.
|
||||
app.MapPrometheusScrapingEndpoint();
|
||||
|
||||
// Submit a registration. The aggregate is created (INGEDIEND) and the registratie process started;
|
||||
// the zaak is opened later, off the request path, by the worker — so this returns 202 Accepted with
|
||||
// a location to read the registration's progress (ADR-0009, eventual consistency).
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.17.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.17.0" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using EventSubscriber.Application;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Projection.ReadModel;
|
||||
@@ -15,7 +16,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): golden signals for the request path —
|
||||
// http.server.request.duration (traffic/errors/latency) + http.client.* for downstream hops, plus
|
||||
// the built-in System.Runtime meter for saturation (GC, CPU, thread pool). Prometheus scrapes these
|
||||
// from /metrics (mapped below); metrics aren't pushed over OTLP, so no collector hop (ADR-0023).
|
||||
.WithMetrics(metrics => metrics
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddMeter("System.Runtime")
|
||||
.AddPrometheusExporter());
|
||||
|
||||
var connectionString = builder.Configuration.GetConnectionString("Projection")
|
||||
?? throw new InvalidOperationException("Missing connection string 'ConnectionStrings:Projection'");
|
||||
@@ -41,6 +51,9 @@ await app.Services.MigrateProjectionAsync();
|
||||
|
||||
app.MapGet("/health", () => "Healthy");
|
||||
|
||||
// Prometheus scrape endpoint (S-16c): exposes the OTel metrics above in Prometheus text format.
|
||||
app.MapPrometheusScrapingEndpoint();
|
||||
|
||||
// The NRC abonnement callback. Open Notificaties POSTs a notification here; we project it.
|
||||
// Auth-on-callback is mandatory: the auth check runs *before* the body is read, so NRC's
|
||||
// registration probe (a POST without the configured Authorization, and without a valid
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Projection.ReadModel;
|
||||
@@ -14,7 +15,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): golden signals for the request path —
|
||||
// http.server.request.duration (traffic/errors/latency) + http.client.* for downstream hops, plus
|
||||
// the built-in System.Runtime meter for saturation (GC, CPU, thread pool). Prometheus scrapes these
|
||||
// from /metrics (mapped below); metrics aren't pushed over OTLP, so no collector hop (ADR-0023).
|
||||
.WithMetrics(metrics => metrics
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddMeter("System.Runtime")
|
||||
.AddPrometheusExporter());
|
||||
|
||||
var connectionString = builder.Configuration.GetConnectionString("Projection")
|
||||
?? throw new InvalidOperationException("Missing connection string 'ConnectionStrings:Projection'");
|
||||
@@ -30,6 +40,9 @@ await app.Services.MigrateProjectionAsync();
|
||||
|
||||
app.MapGet("/health", () => "Healthy");
|
||||
|
||||
// Prometheus scrape endpoint (S-16c): exposes the OTel metrics above in Prometheus text format.
|
||||
app.MapPrometheusScrapingEndpoint();
|
||||
|
||||
// The read side of the projection. Public-safe field filtering is tightened in S-09; for now
|
||||
// the minimal projection only carries id + status (bsn/naam deferred — ADR-0008).
|
||||
app.MapGet("/register", async (ProjectionDbContext db, CancellationToken ct) =>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.17.0-beta.1" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.17.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.17.0" />
|
||||
|
||||
Reference in New Issue
Block a user