feat(historian): backend registry, ServerHistorian:Backend, Host wiring via provider
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -37,6 +37,11 @@ public static class ContinuousHistorizationMetrics
|
||||
ObserveDropped,
|
||||
unit: "{entry}",
|
||||
description: "Lifetime entries the continuous-historization outbox dropped on capacity overflow.");
|
||||
OtOpcUaTelemetry.Meter.CreateObservableGauge(
|
||||
"otopcua.historian.outbox.unreadable",
|
||||
() => _outbox?.UnreadableCount ?? 0L,
|
||||
unit: "{entry}",
|
||||
description: "Lifetime undecodable records the continuous-historization outbox skipped.");
|
||||
}
|
||||
|
||||
/// <summary>Binds the process outbox the gauges observe. Called once by the Host when continuous
|
||||
|
||||
@@ -35,6 +35,20 @@ public sealed class ServerHistorianOptions
|
||||
/// The scheme selects the transport: <c>https://</c> = TLS, <c>http://</c> = h2c plaintext.
|
||||
/// Required when <see cref="Enabled"/> is <c>true</c>.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Selects the historian backend provider (case-insensitive). Default <c>"Gateway"</c>; the Host's
|
||||
/// <c>HistorianBackendRegistry</c> owns the set of valid names. Gateway-specific keys
|
||||
/// (<see cref="Endpoint"/>, <see cref="ApiKey"/>, <see cref="UseTls"/>) are only required for <c>Gateway</c>.
|
||||
/// </summary>
|
||||
public string Backend { get; init; } = GatewayBackendName;
|
||||
|
||||
/// <summary>The default backend name.</summary>
|
||||
public const string GatewayBackendName = "Gateway";
|
||||
|
||||
/// <summary>True when <see cref="Backend"/> selects the gateway backend (case-insensitive).</summary>
|
||||
public bool IsGatewayBackend =>
|
||||
string.Equals(Backend?.Trim(), GatewayBackendName, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public string Endpoint { get; init; } = "";
|
||||
|
||||
/// <summary>
|
||||
@@ -112,6 +126,9 @@ public sealed class ServerHistorianOptions
|
||||
{
|
||||
var warnings = new List<string>();
|
||||
if (!Enabled) return warnings;
|
||||
// Gateway-specific checks apply only to the Gateway backend (other backends carry their own options).
|
||||
if (IsGatewayBackend)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Endpoint))
|
||||
warnings.Add("ServerHistorian:Endpoint is empty while the historian is enabled — the read client has no gateway address to dial.");
|
||||
// archreview 06/S-11 warning parity: a non-empty but unparseable / non-absolute-http(s) Endpoint
|
||||
@@ -123,6 +140,7 @@ public sealed class ServerHistorianOptions
|
||||
warnings.Add($"ServerHistorian:Endpoint ('{Endpoint}') is not an absolute http(s) URI while the historian is enabled — the read client cannot dial it (e.g. https://host:5222).");
|
||||
if (string.IsNullOrWhiteSpace(ApiKey))
|
||||
warnings.Add("ServerHistorian:ApiKey is empty while the historian is enabled — the gateway gRPC surface will reject unauthenticated calls.");
|
||||
}
|
||||
// MaxTieClusterOverfetch is intentionally checked AFTER the Enabled early-return above:
|
||||
// the over-fetch code path only runs when a real IHistorianDataSource is wired in,
|
||||
// so a zero/negative value is harmless (and noise-free) when the historian is disabled.
|
||||
|
||||
Reference in New Issue
Block a user