< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.WebApi.Metrics.MetricsConfiguration
Assembly: ArturRios.Heimdall.WebApi
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Presentation/ArturRios.Heimdall.WebApi/Metrics/MetricsConfiguration.cs
Line coverage
100%
Covered lines: 21
Uncovered lines: 0
Coverable lines: 21
Total lines: 95
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage
100%
Covered methods: 3
Fully covered methods: 3
Total methods: 3
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
AddHeimdallMetrics(...)100%22100%
UseHeimdallMetrics(...)100%22100%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Presentation/ArturRios.Heimdall.WebApi/Metrics/MetricsConfiguration.cs

#LineLine coverage
 1using ArturRios.Heimdall.WebApi.Retention;
 2using OpenTelemetry.Metrics;
 3using OpenTelemetry.Resources;
 4
 5namespace ArturRios.Heimdall.WebApi.Metrics;
 6
 7/// <summary>
 8///     Registers the OpenTelemetry metrics pipeline and mounts its Prometheus scrape endpoint. Both
 9///     halves live here rather than inline in <c>Startup</c> so the tests can build a host with
 10///     exactly this wiring and prove which requests reach the exporter — <c>Startup</c> itself
 11///     cannot be exercised on the metrics port, because the in-memory test server reports a local
 12///     port of <c>0</c> for every request.
 13/// </summary>
 14public static class MetricsConfiguration
 15{
 16    /// <summary>The <c>service.name</c> every series carries, so dashboards can tell this API apart.</summary>
 17    public const string ServiceName = "heimdall-api";
 18
 19    /// <summary>
 20    ///     Meters that ship inside the runtime and the frameworks the API already uses, subscribed to by
 21    ///     name. None of them costs a package: each is emitted whether or not anything listens, and
 22    ///     naming it here is what makes the exporter collect it.
 23    /// </summary>
 24    /// <remarks>
 25    ///     <list type="bullet">
 26    ///         <item>
 27    ///             <c>System.Runtime</c> — GC, heap, thread pool, exceptions, CPU. Built into .NET 9
 28    ///             and later, which is what replaces the OpenTelemetry.Instrumentation.Runtime package.
 29    ///         </item>
 30    ///         <item>
 31    ///             <c>Microsoft.AspNetCore.Server.Kestrel</c> — connections, queued requests, TLS
 32    ///             handshakes. <c>AddAspNetCoreInstrumentation</c> subscribes to it as well; it is named
 33    ///             again so removing that call would not quietly take the connection metrics with it.
 34    ///         </item>
 35    ///         <item>
 36    ///             <c>Microsoft.EntityFrameworkCore</c> — active contexts, queries, SaveChanges and
 37    ///             optimistic-concurrency failures (EF Core 9 and later).
 38    ///         </item>
 39    ///         <item>
 40    ///             <c>Npgsql</c> — connection pool usage, command duration and failures: the first
 41    ///             place a saturated or unreachable database shows.
 42    ///         </item>
 43    ///         <item>
 44    ///             <c>ArturRios.Heimdall.ScheduledPasses</c> — this API's own: rows processed and the time
 45    ///             of the last successful run, per scheduled pass (#214).
 46    ///         </item>
 47    ///     </list>
 48    /// </remarks>
 249    private static readonly string[] BuiltInMeters =
 250    [
 251        "System.Runtime",
 252        "Microsoft.AspNetCore.Server.Kestrel",
 253        "Microsoft.EntityFrameworkCore",
 254        "Npgsql",
 255        ScheduledPassMetrics.MeterName
 256    ];
 57
 58    /// <summary>
 59    ///     Registers the metrics pipeline, or nothing at all when <paramref name="options" /> has
 60    ///     metrics switched off — no meter listener, no exporter, no collection cost.
 61    /// </summary>
 62    public static IServiceCollection AddHeimdallMetrics(this IServiceCollection services, MetricsOptions options)
 63    {
 97664        if (!options.Enabled)
 65        {
 166            return services;
 67        }
 68
 97569        services.AddOpenTelemetry()
 96870            .ConfigureResource(resource => resource.AddService(ServiceName))
 195071            .WithMetrics(metrics => metrics
 195072                .AddAspNetCoreInstrumentation()
 195073                .AddHttpClientInstrumentation()
 195074                .AddMeter(BuiltInMeters)
 195075                .AddPrometheusExporter());
 76
 97577        return services;
 78    }
 79
 80    /// <summary>
 81    ///     Mounts the scrape endpoint behind <see cref="MetricsOptions.IsScrapeRequest" />. It must be
 82    ///     called before anything else in the pipeline: the endpoint is a terminal branch, so a
 83    ///     request it takes never reaches CORS, rate limiting, authentication, authorization or MVC —
 84    ///     and, not being a controller action, it never appears in the OpenAPI document either.
 85    /// </summary>
 86    public static IApplicationBuilder UseHeimdallMetrics(this IApplicationBuilder app, MetricsOptions options)
 87    {
 96988        if (!options.Enabled)
 89        {
 190            return app;
 91        }
 92
 96893        return app.UseOpenTelemetryPrometheusScrapingEndpoint(options.IsScrapeRequest);
 94    }
 95}