Phase 0 — mechanical rename ZB.MOM.WW.LmxOpcUa.* → ZB.MOM.WW.OtOpcUa.*

Renames all 11 projects (5 src + 6 tests), the .slnx solution file, all source-file namespaces, all axaml namespace references, and all v1 documentation references in CLAUDE.md and docs/*.md (excluding docs/v2/ which is already in OtOpcUa form). Also updates the TopShelf service registration name from "LmxOpcUa" to "OtOpcUa" per Phase 0 Task 0.6.

Preserves runtime identifiers per Phase 0 Out-of-Scope rules to avoid breaking v1/v2 client trust during coexistence: OPC UA `ApplicationUri` defaults (`urn:{GalaxyName}:LmxOpcUa`), server `EndpointPath` (`/LmxOpcUa`), `ServerName` default (feeds cert subject CN), `MxAccessConfiguration.ClientName` default (defensive — stays "LmxOpcUa" for MxAccess audit-trail consistency), client OPC UA identifiers (`ApplicationName = "LmxOpcUaClient"`, `ApplicationUri = "urn:localhost:LmxOpcUaClient"`, cert directory `%LocalAppData%\LmxOpcUaClient\pki\`), and the `LmxOpcUaServer` class name (class rename out of Phase 0 scope per Task 0.5 sed pattern; happens in Phase 1 alongside `LmxNodeManager → GenericDriverNodeManager` Core extraction). 23 LmxOpcUa references retained, all enumerated and justified in `docs/v2/implementation/exit-gate-phase-0.md`.

Build clean: 0 errors, 30 warnings (lower than baseline 167). Tests at strict improvement over baseline: 821 passing / 1 failing vs baseline 820 / 2 (one flaky pre-existing failure passed this run; the other still fails — both pre-existing and unrelated to the rename). `Client.UI.Tests`, `Historian.Aveva.Tests`, `Client.Shared.Tests`, `IntegrationTests` all match baseline exactly. Exit gate compliance results recorded in `docs/v2/implementation/exit-gate-phase-0.md` with all 7 checks PASS or DEFERRED-to-PR-review (#7 service install verification needs Windows service permissions on the reviewer's box).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-04-17 13:57:47 -04:00
parent 5b8d708c58
commit 3b2defd94f
293 changed files with 841 additions and 722 deletions

View File

@@ -0,0 +1,570 @@
using System;
using System.Collections.Generic;
using ZB.MOM.WW.OtOpcUa.Host.Domain;
using ZB.MOM.WW.OtOpcUa.Host.Metrics;
namespace ZB.MOM.WW.OtOpcUa.Host.Status
{
/// <summary>
/// DTO containing all dashboard data. (DASH-001 through DASH-009)
/// </summary>
public class StatusData
{
/// <summary>
/// Gets or sets the current MXAccess and service connectivity summary shown on the dashboard.
/// </summary>
public ConnectionInfo Connection { get; set; } = new();
/// <summary>
/// Gets or sets the overall health state communicated to operators.
/// </summary>
public HealthInfo Health { get; set; } = new();
/// <summary>
/// Gets or sets subscription counts that show how many live tag streams the bridge is maintaining.
/// </summary>
public SubscriptionInfo Subscriptions { get; set; } = new();
/// <summary>
/// Gets or sets Galaxy-specific metadata such as deploy timing and address-space counts.
/// </summary>
public GalaxyInfo Galaxy { get; set; } = new();
/// <summary>
/// Gets or sets MXAccess data change dispatch queue metrics.
/// </summary>
public DataChangeInfo DataChange { get; set; } = new();
/// <summary>
/// Gets or sets per-operation performance statistics used to diagnose bridge throughput and latency.
/// </summary>
public Dictionary<string, MetricsStatistics> Operations { get; set; } = new();
/// <summary>
/// Gets or sets the historian integration status (plugin load outcome, server target).
/// </summary>
public HistorianStatusInfo Historian { get; set; } = new();
/// <summary>
/// Gets or sets the alarm integration status and event counters.
/// </summary>
public AlarmStatusInfo Alarms { get; set; } = new();
/// <summary>
/// Gets or sets the redundancy state when redundancy is enabled.
/// </summary>
public RedundancyInfo? Redundancy { get; set; }
/// <summary>
/// Gets or sets the listening OPC UA endpoints and active security profiles.
/// </summary>
public EndpointsInfo Endpoints { get; set; } = new();
/// <summary>
/// Gets or sets the Galaxy runtime host state (Platforms + AppEngines).
/// </summary>
public RuntimeStatusInfo RuntimeStatus { get; set; } = new();
/// <summary>
/// Gets or sets footer details such as the snapshot timestamp and service version.
/// </summary>
public FooterInfo Footer { get; set; } = new();
}
/// <summary>
/// Dashboard model summarizing per-host Galaxy runtime state.
/// </summary>
public class RuntimeStatusInfo
{
/// <summary>
/// Gets or sets the total number of tracked runtime hosts ($WinPlatform + $AppEngine).
/// </summary>
public int Total { get; set; }
/// <summary>
/// Gets or sets the count of hosts currently reported Running.
/// </summary>
public int RunningCount { get; set; }
/// <summary>
/// Gets or sets the count of hosts currently reported Stopped.
/// </summary>
public int StoppedCount { get; set; }
/// <summary>
/// Gets or sets the count of hosts whose state is still Unknown (either awaiting initial
/// probe resolution or transported-through-disconnected).
/// </summary>
public int UnknownCount { get; set; }
/// <summary>
/// Gets or sets the per-host state in stable alphabetical order.
/// </summary>
public List<GalaxyRuntimeStatus> Hosts { get; set; } = new();
}
/// <summary>
/// Dashboard model describing the OPC UA server's listening endpoints and active security profiles.
/// </summary>
public class EndpointsInfo
{
/// <summary>
/// Gets or sets the list of opc.tcp base addresses the server is listening on.
/// </summary>
public List<string> BaseAddresses { get; set; } = new();
/// <summary>
/// Gets or sets the list of configured user token policies (Anonymous, UserName, Certificate).
/// </summary>
public List<string> UserTokenPolicies { get; set; } = new();
/// <summary>
/// Gets or sets the active security profiles reported to clients.
/// </summary>
public List<SecurityProfileInfo> SecurityProfiles { get; set; } = new();
}
/// <summary>
/// Dashboard model for a single configured OPC UA server security profile.
/// </summary>
public class SecurityProfileInfo
{
/// <summary>
/// Gets or sets the OPC UA security policy URI (e.g., http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256).
/// </summary>
public string PolicyUri { get; set; } = "";
/// <summary>
/// Gets or sets the short policy name extracted from the policy URI.
/// </summary>
public string PolicyName { get; set; } = "";
/// <summary>
/// Gets or sets the message security mode (None, Sign, SignAndEncrypt).
/// </summary>
public string SecurityMode { get; set; } = "";
}
/// <summary>
/// Dashboard model for current runtime connection details.
/// </summary>
public class ConnectionInfo
{
/// <summary>
/// Gets or sets the current MXAccess connection state shown to operators.
/// </summary>
public string State { get; set; } = "Disconnected";
/// <summary>
/// Gets or sets how many reconnect attempts have occurred since the service started.
/// </summary>
public int ReconnectCount { get; set; }
/// <summary>
/// Gets or sets the number of active OPC UA sessions connected to the bridge.
/// </summary>
public int ActiveSessions { get; set; }
}
/// <summary>
/// Dashboard model for the overall health banner.
/// </summary>
public class HealthInfo
{
/// <summary>
/// Gets or sets the high-level health state, such as Healthy, Degraded, or Unhealthy.
/// </summary>
public string Status { get; set; } = "Unknown";
/// <summary>
/// Gets or sets the operator-facing explanation for the current health state.
/// </summary>
public string Message { get; set; } = "";
/// <summary>
/// Gets or sets the color token used by the dashboard UI to render the health banner.
/// </summary>
public string Color { get; set; } = "gray";
}
/// <summary>
/// Dashboard model for subscription load.
/// </summary>
public class SubscriptionInfo
{
/// <summary>
/// Gets or sets the number of active tag subscriptions mirrored from MXAccess into OPC UA.
/// This total includes bridge-owned runtime status probes; see <see cref="ProbeCount"/> for the
/// subset attributable to probes.
/// </summary>
public int ActiveCount { get; set; }
/// <summary>
/// Gets or sets the count of bridge-owned runtime status probes included in
/// <see cref="ActiveCount"/>. Surfaced on the dashboard so operators can distinguish probe
/// overhead from client-driven subscription load.
/// </summary>
public int ProbeCount { get; set; }
}
/// <summary>
/// Dashboard model for Galaxy metadata and rebuild status.
/// </summary>
public class GalaxyInfo
{
/// <summary>
/// Gets or sets the Galaxy name currently being bridged into OPC UA.
/// </summary>
public string GalaxyName { get; set; } = "";
/// <summary>
/// Gets or sets a value indicating whether the repository database is currently reachable.
/// </summary>
public bool DbConnected { get; set; }
/// <summary>
/// Gets or sets the most recent deploy timestamp observed in the Galaxy repository.
/// </summary>
public DateTime? LastDeployTime { get; set; }
/// <summary>
/// Gets or sets the number of Galaxy objects currently represented in the address space.
/// </summary>
public int ObjectCount { get; set; }
/// <summary>
/// Gets or sets the number of Galaxy attributes currently represented as OPC UA variables.
/// </summary>
public int AttributeCount { get; set; }
/// <summary>
/// Gets or sets the UTC timestamp of the last completed address-space rebuild.
/// </summary>
public DateTime? LastRebuildTime { get; set; }
}
/// <summary>
/// Dashboard model for MXAccess data change dispatch metrics.
/// </summary>
public class DataChangeInfo
{
/// <summary>
/// Gets or sets the rate of MXAccess data change events received per second.
/// </summary>
public double EventsPerSecond { get; set; }
/// <summary>
/// Gets or sets the average number of items processed per dispatch cycle.
/// </summary>
public double AvgBatchSize { get; set; }
/// <summary>
/// Gets or sets the number of items currently waiting in the dispatch queue.
/// </summary>
public int PendingItems { get; set; }
/// <summary>
/// Gets or sets the total MXAccess data change events received since startup.
/// </summary>
public long TotalEvents { get; set; }
}
/// <summary>
/// Dashboard model for the Wonderware historian integration (runtime-loaded plugin).
/// </summary>
public class HistorianStatusInfo
{
/// <summary>
/// Gets or sets a value indicating whether historian support is enabled in configuration.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the most recent plugin load outcome as a string.
/// Values: <c>Disabled</c>, <c>NotFound</c>, <c>LoadFailed</c>, <c>Loaded</c>.
/// </summary>
public string PluginStatus { get; set; } = "Disabled";
/// <summary>
/// Gets or sets the error message from the last load attempt when <see cref="PluginStatus"/> is <c>LoadFailed</c>.
/// </summary>
public string? PluginError { get; set; }
/// <summary>
/// Gets or sets the absolute path the loader probed for the plugin assembly.
/// </summary>
public string PluginPath { get; set; } = "";
/// <summary>
/// Gets or sets the configured historian server hostname.
/// </summary>
public string ServerName { get; set; } = "";
/// <summary>
/// Gets or sets the configured historian TCP port.
/// </summary>
public int Port { get; set; }
/// <summary>
/// Gets or sets the total number of historian read queries attempted since startup.
/// </summary>
public long QueryTotal { get; set; }
/// <summary>
/// Gets or sets the number of historian queries that completed without an exception.
/// </summary>
public long QuerySuccesses { get; set; }
/// <summary>
/// Gets or sets the number of historian queries that raised an exception.
/// </summary>
public long QueryFailures { get; set; }
/// <summary>
/// Gets or sets the number of consecutive failures since the last successful query.
/// </summary>
public int ConsecutiveFailures { get; set; }
/// <summary>
/// Gets or sets the UTC timestamp of the last successful query.
/// </summary>
public DateTime? LastSuccessTime { get; set; }
/// <summary>
/// Gets or sets the UTC timestamp of the last query failure.
/// </summary>
public DateTime? LastFailureTime { get; set; }
/// <summary>
/// Gets or sets the exception message from the most recent failure.
/// </summary>
public string? LastQueryError { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the plugin currently holds an open process-path
/// SDK connection.
/// </summary>
public bool ProcessConnectionOpen { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the plugin currently holds an open event-path
/// SDK connection.
/// </summary>
public bool EventConnectionOpen { get; set; }
/// <summary>
/// Gets or sets the total number of configured historian cluster nodes.
/// </summary>
public int NodeCount { get; set; }
/// <summary>
/// Gets or sets the number of cluster nodes currently eligible for new connections
/// (i.e., not in failure cooldown).
/// </summary>
public int HealthyNodeCount { get; set; }
/// <summary>
/// Gets or sets the node currently serving process (historical value) queries, or null
/// when no process connection is open.
/// </summary>
public string? ActiveProcessNode { get; set; }
/// <summary>
/// Gets or sets the node currently serving event (alarm history) queries, or null when
/// no event connection is open.
/// </summary>
public string? ActiveEventNode { get; set; }
/// <summary>
/// Gets or sets the per-node cluster state in configuration order.
/// </summary>
public List<Historian.HistorianClusterNodeState> Nodes { get; set; } = new();
}
/// <summary>
/// Dashboard model for alarm integration health and event counters.
/// </summary>
public class AlarmStatusInfo
{
/// <summary>
/// Gets or sets a value indicating whether alarm condition tracking is enabled in configuration.
/// </summary>
public bool TrackingEnabled { get; set; }
/// <summary>
/// Gets or sets the number of distinct alarm conditions currently tracked.
/// </summary>
public int ConditionCount { get; set; }
/// <summary>
/// Gets or sets the number of alarms currently in the InAlarm=true state.
/// </summary>
public int ActiveAlarmCount { get; set; }
/// <summary>
/// Gets or sets the total number of InAlarm transitions observed since startup.
/// </summary>
public long TransitionCount { get; set; }
/// <summary>
/// Gets or sets the total number of alarm acknowledgement transitions observed since startup.
/// </summary>
public long AckEventCount { get; set; }
/// <summary>
/// Gets or sets the total number of alarm acknowledgement MXAccess writes that have failed since startup.
/// </summary>
public long AckWriteFailures { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the template-based alarm object filter is active.
/// </summary>
public bool FilterEnabled { get; set; }
/// <summary>
/// Gets or sets the number of compiled alarm filter patterns.
/// </summary>
public int FilterPatternCount { get; set; }
/// <summary>
/// Gets or sets the number of Galaxy objects included by the alarm filter during the most recent build.
/// </summary>
public int FilterIncludedObjectCount { get; set; }
/// <summary>
/// Gets or sets the raw alarm filter patterns exactly as configured, for dashboard display.
/// </summary>
public List<string> FilterPatterns { get; set; } = new();
}
/// <summary>
/// Dashboard model for redundancy state. Only populated when redundancy is enabled.
/// </summary>
public class RedundancyInfo
{
/// <summary>
/// Gets or sets whether redundancy is enabled.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the redundancy mode (e.g., "Warm", "Hot").
/// </summary>
public string Mode { get; set; } = "";
/// <summary>
/// Gets or sets this instance's role ("Primary" or "Secondary").
/// </summary>
public string Role { get; set; } = "";
/// <summary>
/// Gets or sets the current ServiceLevel byte.
/// </summary>
public byte ServiceLevel { get; set; }
/// <summary>
/// Gets or sets this instance's ApplicationUri.
/// </summary>
public string ApplicationUri { get; set; } = "";
/// <summary>
/// Gets or sets the list of all server URIs in the redundant set.
/// </summary>
public List<string> ServerUris { get; set; } = new();
}
/// <summary>
/// DTO for the /api/health endpoint. Includes component-level health, ServiceLevel, and redundancy state.
/// </summary>
public class HealthEndpointData
{
/// <summary>
/// Gets or sets the overall health status: Healthy, Degraded, or Unhealthy.
/// </summary>
public string Status { get; set; } = "Unknown";
/// <summary>
/// Gets or sets the computed OPC UA ServiceLevel byte (0-255). Only meaningful when redundancy is enabled.
/// </summary>
public byte ServiceLevel { get; set; }
/// <summary>
/// Gets or sets whether redundancy is enabled.
/// </summary>
public bool RedundancyEnabled { get; set; }
/// <summary>
/// Gets or sets this instance's redundancy role when enabled (Primary/Secondary), or null when disabled.
/// </summary>
public string? RedundancyRole { get; set; }
/// <summary>
/// Gets or sets the redundancy mode when enabled (Warm/Hot), or null when disabled.
/// </summary>
public string? RedundancyMode { get; set; }
/// <summary>
/// Gets or sets the per-component health breakdown.
/// </summary>
public ComponentHealth Components { get; set; } = new();
/// <summary>
/// Gets or sets the server uptime since the health endpoint was initialized.
/// </summary>
public string Uptime { get; set; } = "";
/// <summary>
/// Gets or sets the UTC timestamp of this health snapshot.
/// </summary>
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}
/// <summary>
/// Per-component health breakdown for the health endpoint.
/// </summary>
public class ComponentHealth
{
/// <summary>
/// Gets or sets MXAccess runtime connectivity status.
/// </summary>
public string MxAccess { get; set; } = "Disconnected";
/// <summary>
/// Gets or sets Galaxy repository database connectivity status.
/// </summary>
public string Database { get; set; } = "Disconnected";
/// <summary>
/// Gets or sets OPC UA server status.
/// </summary>
public string OpcUaServer { get; set; } = "Stopped";
/// <summary>
/// Gets or sets the historian plugin status.
/// Values: <c>Disabled</c>, <c>NotFound</c>, <c>LoadFailed</c>, <c>Loaded</c>.
/// </summary>
public string Historian { get; set; } = "Disabled";
/// <summary>
/// Gets or sets whether alarm condition tracking is enabled.
/// Values: <c>Disabled</c>, <c>Enabled</c>.
/// </summary>
public string Alarms { get; set; } = "Disabled";
}
/// <summary>
/// Dashboard model for the status page footer.
/// </summary>
public class FooterInfo
{
/// <summary>
/// Gets or sets the UTC time when the status snapshot was generated.
/// </summary>
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the service version displayed to operators for support and traceability.
/// </summary>
public string Version { get; set; } = "";
}
}