From 9c99899322dc71d716600e19630309b2951cc75d Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sat, 16 May 2026 11:23:48 +0300 Subject: [PATCH] Include reporter in endpoint health report --- .../rap-node-agent/cmd/rap-node-agent/main.go | 26 ++++++++++--------- .../cmd/rap-node-agent/main_test.go | 1 + .../DISTRIBUTED_FABRIC_NODE_PROTOCOL_PLAN.md | 2 ++ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/agents/rap-node-agent/cmd/rap-node-agent/main.go b/agents/rap-node-agent/cmd/rap-node-agent/main.go index b7c1355..c387b57 100644 --- a/agents/rap-node-agent/cmd/rap-node-agent/main.go +++ b/agents/rap-node-agent/cmd/rap-node-agent/main.go @@ -499,12 +499,13 @@ func (s *vpnFabricEndpointObservationStore) Report(observedAt time.Time, maxEntr snapshot := s.Snapshot() if len(snapshot) == 0 { return map[string]any{ - "schema_version": "rap.vpn_fabric_endpoint_health_report.v1", - "observed_at": observedAt.UTC().Format(time.RFC3339Nano), - "total": 0, - "reported": 0, - "dropped": 0, - "observations": []mesh.EndpointCandidateHealthObservation{}, + "schema_version": "rap.vpn_fabric_endpoint_health_report.v1", + "reporter_node_id": s.reporterNodeID, + "observed_at": observedAt.UTC().Format(time.RFC3339Nano), + "total": 0, + "reported": 0, + "dropped": 0, + "observations": []mesh.EndpointCandidateHealthObservation{}, } } values := make([]mesh.EndpointCandidateHealthObservation, 0, len(snapshot)) @@ -522,12 +523,13 @@ func (s *vpnFabricEndpointObservationStore) Report(observedAt time.Time, maxEntr } reported := values[:maxEntries] return map[string]any{ - "schema_version": "rap.vpn_fabric_endpoint_health_report.v1", - "observed_at": observedAt.UTC().Format(time.RFC3339Nano), - "total": len(values), - "reported": len(reported), - "dropped": len(values) - len(reported), - "observations": reported, + "schema_version": "rap.vpn_fabric_endpoint_health_report.v1", + "reporter_node_id": s.reporterNodeID, + "observed_at": observedAt.UTC().Format(time.RFC3339Nano), + "total": len(values), + "reported": len(reported), + "dropped": len(values) - len(reported), + "observations": reported, } } diff --git a/agents/rap-node-agent/cmd/rap-node-agent/main_test.go b/agents/rap-node-agent/cmd/rap-node-agent/main_test.go index 51db325..0fcadca 100644 --- a/agents/rap-node-agent/cmd/rap-node-agent/main_test.go +++ b/agents/rap-node-agent/cmd/rap-node-agent/main_test.go @@ -804,6 +804,7 @@ func TestVPNFabricEndpointObservationReportIsBoundedAndNewestFirst(t *testing.T) } report := store.Report(base, 1) if report["schema_version"] != "rap.vpn_fabric_endpoint_health_report.v1" || + report["reporter_node_id"] != "node-a" || report["total"] != 2 || report["reported"] != 1 || report["dropped"] != 1 { diff --git a/docs/architecture/DISTRIBUTED_FABRIC_NODE_PROTOCOL_PLAN.md b/docs/architecture/DISTRIBUTED_FABRIC_NODE_PROTOCOL_PLAN.md index 7647a30..5821311 100644 --- a/docs/architecture/DISTRIBUTED_FABRIC_NODE_PROTOCOL_PLAN.md +++ b/docs/architecture/DISTRIBUTED_FABRIC_NODE_PROTOCOL_PLAN.md @@ -345,6 +345,8 @@ those remote health hints with local observations using the newest signal. Endpoint health observations include source and reporter node fields so control plane can distinguish local dial feedback from aggregated or policy-generated health hints. +The endpoint health heartbeat report also includes the reporter node id at the +report level for simpler multi-node ingestion and diagnostics. Deliverables: