c2bdb7d5de
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
126 lines
6.1 KiB
Protocol Buffer
126 lines
6.1 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package telemetry.v1;
|
|
|
|
option csharp_namespace = "ZB.MOM.WW.OtOpcUa.Commons.Protos.Telemetry.V1";
|
|
|
|
import "google/protobuf/timestamp.proto";
|
|
|
|
// Per-cluster mesh Phase 5: the four live-telemetry channels that used to fan out over
|
|
// DistributedPubSub (alerts / script-logs / driver-health / driver-resilience-status) now travel over
|
|
// ONE gRPC server-streaming contract. Central dials each driver node and opens Subscribe; the node
|
|
// streams its own live telemetry as a sequence of TelemetryEvent envelopes.
|
|
//
|
|
// Additive-only field evolution: never renumber or reuse a tag; a pre-field peer must read a new
|
|
// field's proto3 default correctly (that is why nullable domain fields are modelled with `optional`
|
|
// for explicit presence). Locked by the contract test in the Commons test project.
|
|
service TelemetryStreamService {
|
|
rpc Subscribe(TelemetryStreamRequest) returns (stream TelemetryEvent);
|
|
}
|
|
|
|
message TelemetryStreamRequest {
|
|
string correlation_id = 1;
|
|
}
|
|
|
|
message TelemetryEvent {
|
|
string correlation_id = 1;
|
|
oneof event {
|
|
AlarmTransition alarm_transition = 2; // <- "alerts" / AlarmTransitionEvent
|
|
ScriptLog script_log = 3; // <- "script-logs" / ScriptLogEntry
|
|
DriverHealth driver_health = 4; // <- "driver-health" / DriverHealthChanged
|
|
DriverResilienceStatus driver_resilience = 5; // <- "driver-resilience-status" / DriverResilienceStatusChanged
|
|
}
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Commons.Messages.Alerts.AlarmTransitionEvent.
|
|
message AlarmTransition {
|
|
string alarm_id = 1;
|
|
string equipment_path = 2;
|
|
string alarm_name = 3;
|
|
string transition_kind = 4; // string in the record (Activated/Cleared/...); kept as string
|
|
int32 severity = 5;
|
|
string message = 6;
|
|
string user = 7;
|
|
google.protobuf.Timestamp timestamp_utc = 8;
|
|
string alarm_type_name = 9; // record default "AlarmCondition"
|
|
optional string comment = 10; // nullable in the record — presence distinguishes null from ""
|
|
optional bool historize_to_aveva = 11; // bool? in the record — three states (null / true / false)
|
|
repeated string referencing_equipment_paths = 12; // null in the record is treated as empty
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Commons.Messages.Logging.ScriptLogEntry.
|
|
message ScriptLog {
|
|
string script_id = 1;
|
|
string level = 2; // string in the record (Trace/Debug/Information/...); kept as string
|
|
string message = 3;
|
|
google.protobuf.Timestamp timestamp_utc = 4;
|
|
optional string virtual_tag_id = 5; // nullable in the record
|
|
optional string alarm_id = 6; // nullable in the record
|
|
optional string equipment_id = 7; // nullable in the record
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Commons.Messages.Drivers.DriverHealthChanged.
|
|
message DriverHealth {
|
|
string cluster_id = 1;
|
|
string driver_instance_id = 2;
|
|
string state = 3; // DriverState-as-string in the record; kept as string
|
|
google.protobuf.Timestamp last_successful_read_utc = 4; // DateTime? — absent Timestamp encodes null
|
|
optional string last_error = 5; // nullable in the record
|
|
int32 error_count_5min = 6;
|
|
google.protobuf.Timestamp published_utc = 7;
|
|
google.protobuf.Timestamp rediscovery_needed_utc = 8; // DateTime? — absent Timestamp encodes null
|
|
optional string rediscovery_reason = 9; // nullable in the record
|
|
// Per-host connectivity (Gitea #521). proto3 cannot distinguish an absent repeated field from an
|
|
// empty one, and the two mean different things here — "driver is not an IHostConnectivityProbe" vs
|
|
// "it is one and currently knows no hosts" — so the presence flag carries that bit explicitly rather
|
|
// than letting an empty list silently claim the driver has no probe.
|
|
bool has_host_statuses = 10;
|
|
repeated HostConnectivity host_statuses = 11;
|
|
// Authored tags the driver could not build into its poll table (Gitea #541). The same two facts
|
|
// host_statuses needs a flag for — "the driver cannot report skips" vs "it reports none" — are
|
|
// distinguished here by the field's own presence: a singular MESSAGE field has real presence in
|
|
// proto3, which a repeated field does not. So no companion has_ flag (and one would collide: protoc
|
|
// already generates a HasSkippedTags property for this field).
|
|
SkippedTags skipped_tags = 12;
|
|
// Driver diagnostics bag (Gitea #640), e.g. S7's negotiated PDU size. Additive: an old node never sets
|
|
// these and an old central ignores them. A map cannot distinguish absent from empty, and the two differ
|
|
// ("driver has no IDriverDiagnostics" vs "it has one and currently has nothing to say"), so the presence
|
|
// flag carries that bit - the same shape as has_host_statuses.
|
|
bool has_diagnostics = 13;
|
|
map<string, string> diagnostics = 14;
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Core.Abstractions.SkippedTagReport.
|
|
message SkippedTags {
|
|
int32 authored_count = 1;
|
|
// The TRUE total, which may exceed sample.length — the detail list is capped so a deployment that
|
|
// misconfigures thousands of tags cannot inflate a message published on every state change.
|
|
int32 skipped_count = 2;
|
|
repeated SkippedTag sample = 3;
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Core.Abstractions.SkippedTag.
|
|
message SkippedTag {
|
|
string raw_path = 1;
|
|
string reason = 2;
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Core.Abstractions.HostConnectivityStatus.
|
|
message HostConnectivity {
|
|
string host_name = 1;
|
|
string state = 2; // HostState-as-string, matching DriverHealth.state
|
|
google.protobuf.Timestamp last_changed_utc = 3;
|
|
}
|
|
|
|
// Mirrors ZB.MOM.WW.OtOpcUa.Commons.Messages.Drivers.DriverResilienceStatusChanged.
|
|
message DriverResilienceStatus {
|
|
string driver_instance_id = 1;
|
|
string host_name = 2;
|
|
bool breaker_open = 3;
|
|
int32 consecutive_failures = 4;
|
|
int32 current_in_flight = 5;
|
|
google.protobuf.Timestamp last_breaker_open_utc = 6; // DateTime? — absent Timestamp encodes null
|
|
google.protobuf.Timestamp last_sampled_utc = 7;
|
|
google.protobuf.Timestamp published_utc = 8;
|
|
}
|