diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs index 5e69d58f..4e77a18d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Kpi/AuditLogKpiSampleSource.cs @@ -36,11 +36,12 @@ public sealed class AuditLogKpiSampleSource : IKpiSampleSource /// private static readonly TimeSpan Window = TimeSpan.FromHours(1); - // Metric catalog — the exact strings persisted in KpiSample.Metric. Stable - // identifiers the recorder + UI trend charts key on; do not rename. - private const string TotalEventsLastHourMetric = "totalEventsLastHour"; - private const string ErrorEventsLastHourMetric = "errorEventsLastHour"; - private const string BacklogTotalMetric = "backlogTotal"; + // Metric catalog — the exact strings persisted in KpiSample.Metric. All three are + // charted, so they share the public Commons catalog: source + UI trend page key off + // one symbol (#178). Stable identifiers; do not rename (values are persisted). + private const string TotalEventsLastHourMetric = KpiMetrics.AuditLog.TotalEventsLastHour; + private const string ErrorEventsLastHourMetric = KpiMetrics.AuditLog.ErrorEventsLastHour; + private const string BacklogTotalMetric = KpiMetrics.AuditLog.BacklogTotal; private readonly IAuditLogRepository _repository; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs index 17e69792..1656a05f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs @@ -293,9 +293,9 @@ public partial class AuditLogPage : IDisposable /// The metrics rendered in the panel, in display order. private static readonly (string Metric, string Title, string? Unit)[] TrendMetrics = { - ("totalEventsLastHour", "Events / hour", null), - ("errorEventsLastHour", "Error events / hour", null), - ("backlogTotal", "Backlog", null), + (KpiMetrics.AuditLog.TotalEventsLastHour, "Events / hour", null), + (KpiMetrics.AuditLog.ErrorEventsLastHour, "Error events / hour", null), + (KpiMetrics.AuditLog.BacklogTotal, "Backlog", null), }; /// Per-metric series state, keyed by the metric name. diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor index a2381855..b71bfda1 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor @@ -593,13 +593,13 @@ var siteId = _trendSiteId; (_connectionsDownSeries, _connectionsDownAvailable, _connectionsDownError) = - await LoadTrendSeriesAsync("connectionsDown", siteId, fromUtc, toUtc); + await LoadTrendSeriesAsync(KpiMetrics.SiteHealth.ConnectionsDown, siteId, fromUtc, toUtc); (_deadLettersSeries, _deadLettersAvailable, _deadLettersError) = - await LoadTrendSeriesAsync("deadLetters", siteId, fromUtc, toUtc); + await LoadTrendSeriesAsync(KpiMetrics.SiteHealth.DeadLetters, siteId, fromUtc, toUtc); (_scriptErrorsSeries, _scriptErrorsAvailable, _scriptErrorsError) = - await LoadTrendSeriesAsync("scriptErrors", siteId, fromUtc, toUtc); + await LoadTrendSeriesAsync(KpiMetrics.SiteHealth.ScriptErrors, siteId, fromUtc, toUtc); (_sfBufferDepthSeries, _sfBufferDepthAvailable, _sfBufferDepthError) = - await LoadTrendSeriesAsync("sfBufferDepth", siteId, fromUtc, toUtc); + await LoadTrendSeriesAsync(KpiMetrics.SiteHealth.SfBufferDepth, siteId, fromUtc, toUtc); } finally { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor index e2032706..f87c7747 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor @@ -279,11 +279,11 @@ // one metric's failure only blanks that one chart while the others still // render their fetched data — and a throw never breaks the KPI tiles above. (_queueDepthSeries, _queueDepthAvailable, _queueDepthError) = - await LoadSeries("queueDepth", fromUtc, toUtc); + await LoadSeries(KpiMetrics.NotificationOutbox.QueueDepth, fromUtc, toUtc); (_parkedSeries, _parkedAvailable, _parkedError) = - await LoadSeries("parkedCount", fromUtc, toUtc); + await LoadSeries(KpiMetrics.NotificationOutbox.ParkedCount, fromUtc, toUtc); (_deliveredSeries, _deliveredAvailable, _deliveredError) = - await LoadSeries("deliveredLastInterval", fromUtc, toUtc); + await LoadSeries(KpiMetrics.NotificationOutbox.DeliveredLastInterval, fromUtc, toUtc); } finally { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs index 742bfde5..69c14e95 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs @@ -591,11 +591,11 @@ public partial class SiteCallsReport var fromUtc = toUtc - TimeSpan.FromHours(_windowHours); (_bufferedSeries, _bufferedAvailable, _bufferedError) = - await LoadSeriesAsync("buffered", fromUtc, toUtc); + await LoadSeriesAsync(KpiMetrics.SiteCallAudit.Buffered, fromUtc, toUtc); (_parkedSeries, _parkedAvailable, _parkedError) = - await LoadSeriesAsync("parked", fromUtc, toUtc); + await LoadSeriesAsync(KpiMetrics.SiteCallAudit.Parked, fromUtc, toUtc); (_failedSeries, _failedAvailable, _failedError) = - await LoadSeriesAsync("failedLastInterval", fromUtc, toUtc); + await LoadSeriesAsync(KpiMetrics.SiteCallAudit.FailedLastInterval, fromUtc, toUtc); } finally { diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Kpi/KpiMetrics.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Kpi/KpiMetrics.cs new file mode 100644 index 00000000..6ceff384 --- /dev/null +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Kpi/KpiMetrics.cs @@ -0,0 +1,98 @@ +namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi; + +/// +/// Canonical charted KPI metric-name identifiers (M6 "KPI History & +/// Trends") — the value of +/// for every metric a Central UI trend chart renders. Each owning +/// emits +/// these strings and each trend page keys its GetSeriesAsync lookup on the same +/// strings; promoting them to one shared public symbol means the source and the page key +/// off a single declaration, so a future rename becomes a compiler-enforced single edit +/// rather than a silently-blanked chart. +/// +/// +/// +/// Each constant's value is the metric string as persisted in the tall/EAV +/// KpiSample table and matched at query time. These values are therefore part of +/// the on-disk data contract: this catalog is a symbol-promotion of the existing literals, +/// not a rename — changing any value would orphan historical samples. +/// +/// +/// Only the metrics a trend page actually charts are catalogued here. Sources may emit +/// additional internal metrics (e.g. the Notification Outbox stuckCount / +/// oldestPendingAgeSeconds, the Site Call Audit deliveredLastInterval / +/// stuck / oldestPendingAgeSeconds, and the bulk of the Site Health catalog) +/// that no page references; those stay private to their source until a page charts them. +/// Constants are grouped by source via nested static classes mirroring +/// . +/// +/// +public static class KpiMetrics +{ + /// + /// Charted Notification Outbox (#21) metrics — . + /// Rendered by the Central UI Notification Outbox KPIs trend panel. + /// + public static class NotificationOutbox + { + /// Pending-queue depth (rows awaiting delivery). + public const string QueueDepth = "queueDepth"; + + /// Parked-row count. + public const string ParkedCount = "parkedCount"; + + /// Rows delivered in the last KPI interval. + public const string DeliveredLastInterval = "deliveredLastInterval"; + } + + /// + /// Charted Site Call Audit (#22) metrics — . + /// Rendered by the Central UI Site Calls report trend panel. + /// + public static class SiteCallAudit + { + /// Buffered (non-terminal) cached-call count. + public const string Buffered = "buffered"; + + /// Parked cached-call count. + public const string Parked = "parked"; + + /// Cached calls that failed permanently in the last KPI interval. + public const string FailedLastInterval = "failedLastInterval"; + } + + /// + /// Charted Audit Log (#23) metrics — . + /// Rendered by the Central UI Audit Log page trend panel. + /// + public static class AuditLog + { + /// Audit events recorded in the trailing hour. + public const string TotalEventsLastHour = "totalEventsLastHour"; + + /// Error-row audit events recorded in the trailing hour. + public const string ErrorEventsLastHour = "errorEventsLastHour"; + + /// Total pending (not-yet-forwarded) audit backlog. + public const string BacklogTotal = "backlogTotal"; + } + + /// + /// Charted Site Health (#11) metrics — . + /// Rendered by the Central UI Health-dashboard per-site trend panel. + /// + public static class SiteHealth + { + /// Data connections not in the Connected state. + public const string ConnectionsDown = "connectionsDown"; + + /// Dead-letter count reported by the site. + public const string DeadLetters = "deadLetters"; + + /// Script-execution error count reported by the site. + public const string ScriptErrors = "scriptErrors"; + + /// Summed store-and-forward buffer depth across all buffers. + public const string SfBufferDepth = "sfBufferDepth"; + } +} diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/Kpi/SiteHealthKpiSampleSource.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/Kpi/SiteHealthKpiSampleSource.cs index 0ae3ae4b..2ef5a2a4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/Kpi/SiteHealthKpiSampleSource.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/Kpi/SiteHealthKpiSampleSource.cs @@ -34,13 +34,15 @@ namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring.Kpi; public sealed class SiteHealthKpiSampleSource : IKpiSampleSource { // ── Metric catalog (the M6-agreed metric-name strings for this source) ── - // Declaration order matches the emission order in AddSiteSnapshot. + // Declaration order matches the emission order in AddSiteSnapshot. Charted metrics + // share the public Commons catalog so source + UI trend page key off one symbol + // (#178); the uncharted internal metrics stay private here. private const string MetricConnectionsUp = "connectionsUp"; - private const string MetricConnectionsDown = "connectionsDown"; - private const string MetricScriptErrors = "scriptErrors"; + private const string MetricConnectionsDown = KpiMetrics.SiteHealth.ConnectionsDown; + private const string MetricScriptErrors = KpiMetrics.SiteHealth.ScriptErrors; private const string MetricAlarmEvalErrors = "alarmEvalErrors"; - private const string MetricSfBufferDepth = "sfBufferDepth"; - private const string MetricDeadLetters = "deadLetters"; + private const string MetricSfBufferDepth = KpiMetrics.SiteHealth.SfBufferDepth; + private const string MetricDeadLetters = KpiMetrics.SiteHealth.DeadLetters; private const string MetricParkedMessages = "parkedMessages"; private const string MetricDeployedInstances = "deployedInstances"; private const string MetricEnabledInstances = "enabledInstances"; diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Kpi/NotificationOutboxKpiSampleSource.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Kpi/NotificationOutboxKpiSampleSource.cs index e0b0174b..07dc6246 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Kpi/NotificationOutboxKpiSampleSource.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Kpi/NotificationOutboxKpiSampleSource.cs @@ -34,10 +34,12 @@ namespace ZB.MOM.WW.ScadaBridge.NotificationOutbox.Kpi; /// public sealed class NotificationOutboxKpiSampleSource : IKpiSampleSource { - private const string MetricQueueDepth = "queueDepth"; + // Charted metrics share the public Commons catalog so source + UI trend page key + // off one symbol (#178). The uncharted internal metrics stay private here. + private const string MetricQueueDepth = KpiMetrics.NotificationOutbox.QueueDepth; private const string MetricStuckCount = "stuckCount"; - private const string MetricParkedCount = "parkedCount"; - private const string MetricDeliveredLastInterval = "deliveredLastInterval"; + private const string MetricParkedCount = KpiMetrics.NotificationOutbox.ParkedCount; + private const string MetricDeliveredLastInterval = KpiMetrics.NotificationOutbox.DeliveredLastInterval; private const string MetricOldestPendingAgeSeconds = "oldestPendingAgeSeconds"; private readonly INotificationOutboxRepository _repository; diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/Kpi/SiteCallAuditKpiSampleSource.cs b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/Kpi/SiteCallAuditKpiSampleSource.cs index 3accce76..93b59a4a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/Kpi/SiteCallAuditKpiSampleSource.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/Kpi/SiteCallAuditKpiSampleSource.cs @@ -36,10 +36,12 @@ namespace ZB.MOM.WW.ScadaBridge.SiteCallAudit.Kpi; public sealed class SiteCallAuditKpiSampleSource : IKpiSampleSource { // ── Metric catalog (the M6-agreed metric-name strings for this source) ── - // Declaration order matches the emission order in AddSnapshot. - private const string MetricBuffered = "buffered"; - private const string MetricParked = "parked"; - private const string MetricFailedLastInterval = "failedLastInterval"; + // Declaration order matches the emission order in AddSnapshot. Charted metrics + // share the public Commons catalog so source + UI trend page key off one symbol + // (#178); the uncharted internal metrics stay private here. + 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 MetricStuck = "stuck"; private const string MetricOldestPendingAgeSeconds = "oldestPendingAgeSeconds";