< Summary - Heimdall API

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
RowsProcessed(...)100%22100%
Succeeded(...)100%11100%
LastSuccessOf(...)100%22100%

File(s)

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

#LineLine coverage
 1using System.Collections.Concurrent;
 2using System.Diagnostics.Metrics;
 3
 4namespace ArturRios.Heimdall.WebApi.Retention;
 5
 6/// <summary>
 7///     The instruments every scheduled pass reports through, labelled by <c>pass</c>, so an operator can
 8///     alert on "no successful run in N hours" instead of relying on a log line being noticed (#214).
 9/// </summary>
 10/// <remarks>
 11///     Registered on the meter <see cref="MeterName" />, which <c>MetricsConfiguration</c> subscribes the
 12///     exporter to. The instruments exist whether or not metrics are enabled; with nothing listening
 13///     they cost a branch.
 14/// </remarks>
 15public static class ScheduledPassMetrics
 16{
 17    /// <summary>The meter the exporter is told to collect.</summary>
 18    public const string MeterName = "ArturRios.Heimdall.ScheduledPasses";
 19
 120    private static readonly Meter Meter = new(MeterName);
 21
 122    private static readonly Counter<long> Rows = Meter.CreateCounter<long>(
 123        "heimdall.scheduled_pass.rows_processed",
 124        description: "Rows a scheduled pass has changed, by pass.");
 25
 126    private static readonly ConcurrentDictionary<string, long> LastSuccess = new();
 27
 28    // Held only so the instrument is not collected; the callback reads LastSuccess.
 129    private static readonly ObservableGauge<long> LastSuccessGauge = Meter.CreateObservableGauge(
 130        "heimdall.scheduled_pass.last_success_timestamp",
 531        () => LastSuccess.Select(entry => new Measurement<long>(entry.Value, new KeyValuePair<string, object?>("pass", e
 132        description: "Unix time in seconds of the last run of a scheduled pass that completed without failure, by pass."
 33
 34    /// <summary>Adds the rows a run reported to the pass's counter.</summary>
 35    public static void RowsProcessed(string pass, long rows)
 36    {
 1237        if (rows > 0)
 38        {
 639            Rows.Add(rows, new KeyValuePair<string, object?>("pass", pass));
 40        }
 1241    }
 42
 43    /// <summary>Records now as the pass's last successful run.</summary>
 944    public static void Succeeded(string pass) => LastSuccess[pass] = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
 45
 46    /// <summary>The pass's last successful run as unix seconds, or <c>null</c> if it has not succeeded.</summary>
 347    public static long? LastSuccessOf(string pass) => LastSuccess.TryGetValue(pass, out var at) ? at : null;
 48}