fix(kpi): promote catalog metric literals to shared KpiMetrics constants — drift becomes a compile error (plan R2-04 T8)
This commit is contained in:
@@ -42,10 +42,10 @@ public enum KpiRollupAggregation
|
||||
/// Keying by <c>(source, metric)</c> — not metric alone — is deliberate:
|
||||
/// <c>deliveredLastInterval</c> is emitted by both
|
||||
/// <see cref="KpiSources.NotificationOutbox"/> and <see cref="KpiSources.SiteCallAudit"/>,
|
||||
/// so a metric name is not globally unique. Every metric string is taken from the
|
||||
/// emitting source verbatim (shared <see cref="KpiMetrics"/> constants where they exist,
|
||||
/// otherwise the source's own private literal), so this catalog stays a faithful mirror
|
||||
/// of what actually lands in <c>KpiSample.Metric</c>.
|
||||
/// so a metric name is not globally unique. Every catalogued metric string is now a shared
|
||||
/// <see cref="KpiMetrics"/> constant — the emitting source consumes the same constant — so an
|
||||
/// emitter rename is a <strong>compile error</strong>, not a silent Gauge downgrade (R4), and
|
||||
/// this catalog stays a faithful mirror of what actually lands in <c>KpiSample.Metric</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The catalog stores only the <see cref="KpiRollupAggregation.Rate"/> pairs; anything
|
||||
@@ -57,12 +57,6 @@ public enum KpiRollupAggregation
|
||||
/// </remarks>
|
||||
public static class KpiMetricAggregationCatalog
|
||||
{
|
||||
// Metric literals for the sources that keep their names private (no shared
|
||||
// KpiMetrics constant exists for these). Charted metrics use the KpiMetrics catalog.
|
||||
private const string SiteCallAuditDeliveredLastInterval = "deliveredLastInterval";
|
||||
private const string SiteHealthAlarmEvalErrors = "alarmEvalErrors";
|
||||
private const string SiteHealthEventLogWriteFailures = "eventLogWriteFailures";
|
||||
|
||||
/// <summary>
|
||||
/// The <c>(source, metric)</c> pairs classified as <see cref="KpiRollupAggregation.Rate"/>
|
||||
/// (sum-per-hour). Every other emitted metric is a <see cref="KpiRollupAggregation.Gauge"/>.
|
||||
@@ -99,11 +93,11 @@ public static class KpiMetricAggregationCatalog
|
||||
{
|
||||
(KpiSources.NotificationOutbox, KpiMetrics.NotificationOutbox.DeliveredLastInterval),
|
||||
(KpiSources.SiteCallAudit, KpiMetrics.SiteCallAudit.FailedLastInterval),
|
||||
(KpiSources.SiteCallAudit, SiteCallAuditDeliveredLastInterval),
|
||||
(KpiSources.SiteCallAudit, KpiMetrics.SiteCallAudit.DeliveredLastInterval),
|
||||
(KpiSources.SiteHealth, KpiMetrics.SiteHealth.ScriptErrors),
|
||||
(KpiSources.SiteHealth, SiteHealthAlarmEvalErrors),
|
||||
(KpiSources.SiteHealth, KpiMetrics.SiteHealth.AlarmEvalErrors),
|
||||
(KpiSources.SiteHealth, KpiMetrics.SiteHealth.DeadLetters),
|
||||
(KpiSources.SiteHealth, SiteHealthEventLogWriteFailures),
|
||||
(KpiSources.SiteHealth, KpiMetrics.SiteHealth.EventLogWriteFailures),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,11 +18,16 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi;
|
||||
/// <strong>not</strong> a rename — changing any value would orphan historical samples.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Only the metrics a trend page actually charts are catalogued here. Sources may emit
|
||||
/// additional internal metrics (e.g. the Notification Outbox <c>stuckCount</c> /
|
||||
/// <c>oldestPendingAgeSeconds</c>, the Site Call Audit <c>deliveredLastInterval</c> /
|
||||
/// <c>stuck</c> / <c>oldestPendingAgeSeconds</c>, and the bulk of the Site Health catalog)
|
||||
/// that no page references; those stay private to their source until a page charts them.
|
||||
/// This catalog now carries two kinds of metric: those a trend page charts, <em>and</em>
|
||||
/// those the <see cref="KpiMetricAggregationCatalog"/> classifies for the hourly rollup fold
|
||||
/// (e.g. <c>SiteCallAudit/deliveredLastInterval</c>, <c>SiteHealth/alarmEvalErrors</c>,
|
||||
/// <c>SiteHealth/eventLogWriteFailures</c>) even if no page charts them yet. The C4/R4 lesson
|
||||
/// is that <strong>any metric named in two places needs one shared symbol</strong>: a private
|
||||
/// literal on the emitter plus a matching private literal in the catalog drifts silently on a
|
||||
/// rename. Sources may still keep genuinely single-use internal metrics (e.g. the Notification
|
||||
/// Outbox <c>stuckCount</c> / <c>oldestPendingAgeSeconds</c>, the Site Call Audit <c>stuck</c> /
|
||||
/// <c>oldestPendingAgeSeconds</c>, and the bulk of the Site Health catalog) private until a page
|
||||
/// or the catalog references them.
|
||||
/// Constants are grouped by source via nested static classes mirroring
|
||||
/// <see cref="KpiSources"/>.
|
||||
/// </para>
|
||||
@@ -65,6 +70,11 @@ public static class KpiMetrics
|
||||
|
||||
/// <summary>Cached calls that failed permanently in the last KPI interval.</summary>
|
||||
public const string FailedLastInterval = "failedLastInterval";
|
||||
|
||||
/// <summary>Cached calls delivered in the last KPI interval. Not charted by a trend
|
||||
/// page today, but named in the rollup aggregation catalog as a Rate metric — so it
|
||||
/// is a shared symbol to keep the emitter and catalog in lock-step (R4).</summary>
|
||||
public const string DeliveredLastInterval = "deliveredLastInterval";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,6 +108,16 @@ public static class KpiMetrics
|
||||
/// <summary>Script-execution error count reported by the site.</summary>
|
||||
public const string ScriptErrors = "scriptErrors";
|
||||
|
||||
/// <summary>Alarm-evaluation error count reported by the site. Named in the rollup
|
||||
/// aggregation catalog as a Rate metric — shared symbol so an emitter rename is a
|
||||
/// compile error, not a silent Gauge downgrade (R4).</summary>
|
||||
public const string AlarmEvalErrors = "alarmEvalErrors";
|
||||
|
||||
/// <summary>Event-log write-failure count reported by the site. Named in the rollup
|
||||
/// aggregation catalog as a Rate metric — shared symbol so an emitter rename is a
|
||||
/// compile error, not a silent Gauge downgrade (R4).</summary>
|
||||
public const string EventLogWriteFailures = "eventLogWriteFailures";
|
||||
|
||||
/// <summary>Summed store-and-forward buffer depth across all buffers.</summary>
|
||||
public const string SfBufferDepth = "sfBufferDepth";
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public sealed class SiteHealthKpiSampleSource : IKpiSampleSource
|
||||
private const string MetricConnectionsUp = "connectionsUp";
|
||||
private const string MetricConnectionsDown = KpiMetrics.SiteHealth.ConnectionsDown;
|
||||
private const string MetricScriptErrors = KpiMetrics.SiteHealth.ScriptErrors;
|
||||
private const string MetricAlarmEvalErrors = "alarmEvalErrors";
|
||||
private const string MetricAlarmEvalErrors = KpiMetrics.SiteHealth.AlarmEvalErrors;
|
||||
private const string MetricSfBufferDepth = KpiMetrics.SiteHealth.SfBufferDepth;
|
||||
private const string MetricDeadLetters = KpiMetrics.SiteHealth.DeadLetters;
|
||||
private const string MetricParkedMessages = "parkedMessages";
|
||||
@@ -48,7 +48,7 @@ public sealed class SiteHealthKpiSampleSource : IKpiSampleSource
|
||||
private const string MetricEnabledInstances = "enabledInstances";
|
||||
private const string MetricDisabledInstances = "disabledInstances";
|
||||
private const string MetricAuditBacklogPending = "auditBacklogPending";
|
||||
private const string MetricEventLogWriteFailures = "eventLogWriteFailures";
|
||||
private const string MetricEventLogWriteFailures = KpiMetrics.SiteHealth.EventLogWriteFailures;
|
||||
|
||||
private readonly ICentralHealthAggregator _aggregator;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public sealed class SiteCallAuditKpiSampleSource : IKpiSampleSource
|
||||
private const string MetricBuffered = KpiMetrics.SiteCallAudit.Buffered;
|
||||
private const string MetricParked = KpiMetrics.SiteCallAudit.Parked;
|
||||
private const string MetricFailedLastInterval = KpiMetrics.SiteCallAudit.FailedLastInterval;
|
||||
private const string MetricDeliveredLastInterval = "deliveredLastInterval";
|
||||
private const string MetricDeliveredLastInterval = KpiMetrics.SiteCallAudit.DeliveredLastInterval;
|
||||
private const string MetricStuck = "stuck";
|
||||
private const string MetricOldestPendingAgeSeconds = "oldestPendingAgeSeconds";
|
||||
|
||||
|
||||
@@ -148,4 +148,22 @@ public class KpiMetricAggregationTests
|
||||
KpiRollupAggregation.Rate,
|
||||
KpiMetricAggregationCatalog.Resolve(KpiSources.SiteCallAudit, "deliveredLastInterval"));
|
||||
}
|
||||
|
||||
// ---- Task 8: catalog metric literals promoted to shared KpiMetrics constants (R4) ----
|
||||
|
||||
[Fact]
|
||||
public void PromotedMetricConstants_LockHistoricalPersistedValues()
|
||||
{
|
||||
// Persisted data contract — these are symbol promotions, NOT renames.
|
||||
Assert.Equal("deliveredLastInterval", KpiMetrics.SiteCallAudit.DeliveredLastInterval);
|
||||
Assert.Equal("alarmEvalErrors", KpiMetrics.SiteHealth.AlarmEvalErrors);
|
||||
Assert.Equal("eventLogWriteFailures", KpiMetrics.SiteHealth.EventLogWriteFailures);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(KpiSources.SiteCallAudit, KpiMetrics.SiteCallAudit.DeliveredLastInterval)]
|
||||
[InlineData(KpiSources.SiteHealth, KpiMetrics.SiteHealth.AlarmEvalErrors)]
|
||||
[InlineData(KpiSources.SiteHealth, KpiMetrics.SiteHealth.EventLogWriteFailures)]
|
||||
public void Resolve_PromotedRatePairs_StillClassifyAsRate(string source, string metric)
|
||||
=> Assert.Equal(KpiRollupAggregation.Rate, KpiMetricAggregationCatalog.Resolve(source, metric));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user