namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring; public class HealthMonitoringOptions { /// Interval at which sites emit health reports to the central cluster. public TimeSpan ReportInterval { get; set; } = TimeSpan.FromSeconds(30); /// Duration of silence after which a site is classified as offline. public TimeSpan OfflineTimeout { get; set; } = TimeSpan.FromMinutes(1); /// /// Offline timeout applied to the synthetic "central" site only. Real sites /// emit frequent heartbeats that keep LastHeartbeatAt fresh, so the /// normal only fires on genuine total loss. The /// "central" self-report has no heartbeat source — its only signal is the /// 30s , so a single skipped/late /// self-report (leader GC pause, brief stall, mid-failover before the new /// leader's loop spins up) would flap it offline under the 60s site timeout. /// A longer central grace gives the equivalent of "one missed report" that /// the design doc grants real sites. Default: 3x the report interval. /// public TimeSpan CentralOfflineTimeout { get; set; } = TimeSpan.FromMinutes(3); /// /// Duration an online site may go without a full health report /// (heartbeats notwithstanding) before it is flagged /// . Distinct from /// , which is heartbeat-based liveness: a site /// whose HealthReportSender has died keeps heartbeating and stays "online", /// but its metrics freeze — this window surfaces that. Must be positive and /// no shorter than (a window shorter than one /// report interval would flag every healthy site). Default: 2 minutes /// (~4 missed 30s reports). /// public TimeSpan MetricsStaleTimeout { get; set; } = TimeSpan.FromMinutes(2); /// /// Unacked LocalDb replication oplog depth above which a site is considered backlogged /// (register row 33). Crossing this alone shows nothing — the backlog must also stay /// above it for before the Health dashboard /// badges the site. Must be positive. Default: 1000 entries. /// public long LocalDbBacklogThreshold { get; set; } = 1000; /// /// How long the oplog backlog must stay continuously above /// before the Health dashboard badges the site /// (register row 33). /// /// /// This dwell time is the whole point of the signal, not a refinement of it. A bare /// threshold would fire every single day on a healthy replicated site: the `site_events` /// retention purge and the storage-cap trim are CDC-captured like any other write, so the /// backlog jumps by the deleted batch size and then drains as the peer acks it. That spike /// is expected and documented (see docs/deployment/topology-guide.md → *Reading the /// replication backlog*). Healthy means the backlog RETURNS TO ~0; unhealthy means it /// stays up. Only a sustained window can tell those apart, so the default is set well /// clear of a purge drain. Must be positive and no shorter than /// — a window shorter than one report interval could be /// satisfied by a single sample, which is exactly the bare threshold this exists to avoid. /// Default: 15 minutes. /// public TimeSpan LocalDbBacklogSustainedFor { get; set; } = TimeSpan.FromMinutes(15); }