feat(api): enhance peer session tracking and error handling
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 35s
CI / go (push) Successful in 52s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m58s
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 35s
CI / go (push) Successful in 52s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m58s
- Added `PollError` field to `peerSessionOnSpeaker` and `liveSpeakerPoll` types to capture polling errors for speakers. - Updated `matchPeerOnSpeakers` function to handle polling errors and adjust session state reporting. - Modified frontend components to display polling error messages alongside session states, improving user visibility into peer connection statuses. - Enhanced API response structure to include live speaker polling information, facilitating better monitoring of speaker health.
This commit is contained in:
@@ -33,6 +33,15 @@ type peerSessionOnSpeaker struct {
|
||||
SpeakerID string `json:"speaker_id"`
|
||||
Label string `json:"label"`
|
||||
State string `json:"state"`
|
||||
PollError string `json:"poll_error,omitempty"`
|
||||
}
|
||||
|
||||
type liveSpeakerPoll struct {
|
||||
SpeakerID string `json:"speaker_id"`
|
||||
Label string `json:"label"`
|
||||
OK bool `json:"ok"`
|
||||
SessionCount int `json:"session_count"`
|
||||
PollError string `json:"poll_error,omitempty"`
|
||||
}
|
||||
|
||||
func speakerDisplayLabel(sp *store.Speaker) string {
|
||||
@@ -136,6 +145,29 @@ func (s *Server) collectSpeakerBGPLive(ctx context.Context, tenantID string, fre
|
||||
return views
|
||||
}
|
||||
|
||||
func liveSpeakerPollJSON(views []speakerBGPLive) []liveSpeakerPoll {
|
||||
out := make([]liveSpeakerPoll, 0, len(views))
|
||||
for _, v := range views {
|
||||
out = append(out, liveSpeakerPoll{
|
||||
SpeakerID: v.SpeakerID,
|
||||
Label: v.Label,
|
||||
OK: v.Error == "",
|
||||
SessionCount: len(v.Sessions),
|
||||
PollError: v.Error,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func findPeerSession(sessions []birdfmt.BGPSession, protoName string, neighbor netip.Addr, hasNeighbor bool) *birdfmt.BGPSession {
|
||||
for i := range sessions {
|
||||
if peerSessionMatches(sessions[i], protoName, neighbor, hasNeighbor) {
|
||||
return &sessions[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func matchPeerOnSpeakers(peer *store.BGPPeer, views []speakerBGPLive) (
|
||||
bestState string,
|
||||
connectedID string,
|
||||
@@ -152,24 +184,33 @@ func matchPeerOnSpeakers(peer *store.BGPPeer, views []speakerBGPLive) (
|
||||
|
||||
for _, v := range views {
|
||||
if v.Error != "" && len(v.Sessions) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, sess := range v.Sessions {
|
||||
if !peerSessionMatches(sess, protoName, neighbor, hasNeighbor) {
|
||||
continue
|
||||
}
|
||||
hit := peerSessionOnSpeaker{
|
||||
on = append(on, peerSessionOnSpeaker{
|
||||
SpeakerID: v.SpeakerID,
|
||||
Label: v.Label,
|
||||
State: sess.State,
|
||||
}
|
||||
on = append(on, hit)
|
||||
if strings.EqualFold(strings.TrimSpace(sess.State), "Established") {
|
||||
establishedOn = append(establishedOn, hit)
|
||||
}
|
||||
if bestState == "" || sessionStateRank(sess.State) > sessionStateRank(bestState) {
|
||||
bestState = sess.State
|
||||
}
|
||||
PollError: v.Error,
|
||||
})
|
||||
continue
|
||||
}
|
||||
sess := findPeerSession(v.Sessions, protoName, neighbor, hasNeighbor)
|
||||
if sess == nil {
|
||||
on = append(on, peerSessionOnSpeaker{
|
||||
SpeakerID: v.SpeakerID,
|
||||
Label: v.Label,
|
||||
State: "absent",
|
||||
})
|
||||
continue
|
||||
}
|
||||
hit := peerSessionOnSpeaker{
|
||||
SpeakerID: v.SpeakerID,
|
||||
Label: v.Label,
|
||||
State: sess.State,
|
||||
}
|
||||
on = append(on, hit)
|
||||
if strings.EqualFold(strings.TrimSpace(sess.State), "Established") {
|
||||
establishedOn = append(establishedOn, hit)
|
||||
}
|
||||
if bestState == "" || sessionStateRank(sess.State) > sessionStateRank(bestState) {
|
||||
bestState = sess.State
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +224,7 @@ func matchPeerOnSpeakers(peer *store.BGPPeer, views []speakerBGPLive) (
|
||||
if len(establishedOn) == 1 {
|
||||
connectedID = establishedOn[0].SpeakerID
|
||||
}
|
||||
} else if len(on) == 1 {
|
||||
} else if len(on) == 1 && on[0].PollError == "" && on[0].State != "" {
|
||||
connectedID = on[0].SpeakerID
|
||||
connectedLabel = on[0].Label
|
||||
}
|
||||
@@ -209,11 +250,11 @@ func peerSessionMatches(sess birdfmt.BGPSession, protoName string, neighbor neti
|
||||
if !hasNeighbor || strings.TrimSpace(sess.Neighbor) == "" {
|
||||
return false
|
||||
}
|
||||
addr, err := netip.ParseAddr(strings.TrimSpace(sess.Neighbor))
|
||||
if err != nil {
|
||||
peerAddr, ok := store.ParsePeerNeighbor(sess.Neighbor)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return addr == neighbor
|
||||
return peerAddr == neighbor
|
||||
}
|
||||
|
||||
func sessionStateRank(state string) int {
|
||||
@@ -233,26 +274,17 @@ func sessionStateRank(state string) int {
|
||||
|
||||
func applyPeerLiveFields(row map[string]any, peer *store.BGPPeer, views []speakerBGPLive) {
|
||||
state, connID, connLabel, establishedOn, on, mismatch := matchPeerOnSpeakers(peer, views)
|
||||
if len(on) > 0 {
|
||||
if state != "" {
|
||||
row["session_state"] = state
|
||||
}
|
||||
row["connected_speaker_id"] = peerLiveSpeakerIDOrNull(connID)
|
||||
row["connected_speaker_label"] = connLabel
|
||||
row["session_on_speakers"] = on
|
||||
if len(establishedOn) > 0 {
|
||||
row["established_on_speakers"] = establishedOn
|
||||
} else {
|
||||
row["established_on_speakers"] = []peerSessionOnSpeaker{}
|
||||
}
|
||||
row["session_conflict"] = false
|
||||
row["session_mismatch"] = mismatch
|
||||
return
|
||||
}
|
||||
row["session_on_speakers"] = []peerSessionOnSpeaker{}
|
||||
row["established_on_speakers"] = []peerSessionOnSpeaker{}
|
||||
row["session_on_speakers"] = on
|
||||
row["established_on_speakers"] = establishedOn
|
||||
row["session_conflict"] = false
|
||||
row["session_mismatch"] = false
|
||||
row["session_mismatch"] = mismatch
|
||||
if state != "" {
|
||||
row["session_state"] = state
|
||||
}
|
||||
if connLabel != "" {
|
||||
row["connected_speaker_label"] = connLabel
|
||||
}
|
||||
row["connected_speaker_id"] = peerLiveSpeakerIDOrNull(connID)
|
||||
}
|
||||
|
||||
func peerLiveSpeakerIDOrNull(id string) any {
|
||||
|
||||
Reference in New Issue
Block a user