diff --git a/internal/server/grpc_status.go b/internal/server/grpc_status.go index d8e9388..7399e6b 100644 --- a/internal/server/grpc_status.go +++ b/internal/server/grpc_status.go @@ -21,18 +21,15 @@ func (s *HTTPServer) handleGRPC(w http.ResponseWriter, r *http.Request) { http.Error(w, "Failed to get Agent ID", http.StatusInternalServerError) return } - shortName, err := s.store.GetShortName() + + base, err := s.prepareBaseData("gRPC Introspection", "grpc") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } data := GRPCStatusData{ - BaseData: BaseData{ - Title: "gRPC Introspection", - AgentName: shortName, - ActiveNav: "grpc", - }, + BaseData: base, } members, err := s.store.GetMembers() diff --git a/internal/server/http_server.go b/internal/server/http_server.go index ca133a2..8860abf 100644 --- a/internal/server/http_server.go +++ b/internal/server/http_server.go @@ -360,22 +360,10 @@ func (s *HTTPServer) Run(lis net.Listener) error { return http.Serve(lis, withSecurityHeaders(mux)) } -func (s *HTTPServer) handleIndex(w http.ResponseWriter, r *http.Request) { - agentID, err := s.store.GetAgentID() - if err != nil { - http.Error(w, "Failed to get Agent ID", http.StatusInternalServerError) - return - } - shortName, err := s.store.GetShortName() - if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) - return - } - +func (s *HTTPServer) getConsensusMembers() (map[string]state.PeerInfo, error) { val, _, _, _, err := s.store.GetKVEntry(constants.PeersKey) if err != nil { - http.Error(w, "Failed to get peers from KV store", http.StatusInternalServerError) - return + return nil, fmt.Errorf("failed to get peers from KV store: %w", err) } members := make(map[string]state.PeerInfo) if val != nil { @@ -383,37 +371,33 @@ func (s *HTTPServer) handleIndex(w http.ResponseWriter, r *http.Request) { glog.Errorf("Failed to unmarshal peers map: %v", err) } } + return members, nil +} - kvs, err := s.store.GetAllKVs() +func (s *HTTPServer) prepareBaseData(title, activeNav string) (BaseData, error) { + shortName, err := s.store.GetShortName() if err != nil { - http.Error(w, "Failed to get KV store", http.StatusInternalServerError) - return - } - - data := IndexData{ - BaseData: BaseData{ - Title: "Status", - AgentName: shortName, - ActiveNav: "status", - }, - AgentID: template.HTML(fmt.Sprintf(`
%s
`, html.EscapeString(wrapString(agentID, 40)))), - KeysCount: len(kvs), - } - - if ident, err := s.store.GetIdentity(""); err == nil { - data.AgentCert = string(identity.MarshalCertificate(ident.Certificate)) + return BaseData{}, err } + return BaseData{ + Title: title, + AgentName: shortName, + ActiveNav: activeNav, + }, nil +} +func (s *HTTPServer) prepareParticipants(members map[string]state.PeerInfo, selfID string) []Participant { var ids []string for id := range members { ids = append(ids, id) } sort.Strings(ids) + var participants []Participant for _, id := range ids { idWrapped := fmt.Sprintf(`
%s
`, html.EscapeString(wrapString(id, 40))) label := idWrapped - if id == agentID { + if id == selfID { label = fmt.Sprintf("%s self", idWrapped) } info := members[id] @@ -428,13 +412,51 @@ func (s *HTTPServer) handleIndex(w http.ResponseWriter, r *http.Request) { if grpcAddr == "" { grpcAddr = "unknown" } - data.Participants = append(data.Participants, Participant{ + participants = append(participants, Participant{ IDLabel: template.HTML(label), ShortName: info.ShortName, GRPCAddr: grpcAddr, HTTPLink: template.HTML(httpLink), }) } + return participants +} + +func (s *HTTPServer) handleIndex(w http.ResponseWriter, r *http.Request) { + agentID, err := s.store.GetAgentID() + if err != nil { + http.Error(w, "Failed to get Agent ID", http.StatusInternalServerError) + return + } + + base, err := s.prepareBaseData("Status", "status") + if err != nil { + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) + return + } + + members, err := s.getConsensusMembers() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + kvs, err := s.store.GetAllKVs() + if err != nil { + http.Error(w, "Failed to get KV store", http.StatusInternalServerError) + return + } + + data := IndexData{ + BaseData: base, + AgentID: template.HTML(fmt.Sprintf(`
%s
`, html.EscapeString(wrapString(agentID, 40)))), + KeysCount: len(kvs), + Participants: s.prepareParticipants(members, agentID), + } + + if ident, err := s.store.GetIdentity(""); err == nil { + data.AgentCert = string(identity.MarshalCertificate(ident.Certificate)) + } w.Header().Set("Content-Type", "text/html") if err := templates.ExecuteTemplate(w, "index.html", data); err != nil { @@ -449,35 +471,27 @@ func (s *HTTPServer) handleMessages(w http.ResponseWriter, r *http.Request) { http.Error(w, "Failed to get Agent ID", http.StatusInternalServerError) return } - shortName, err := s.store.GetShortName() + + base, err := s.prepareBaseData("Messages", "messages") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } + entries, err := s.store.GetRecentMessages(100) if err != nil { http.Error(w, "Failed to get recent messages", http.StatusInternalServerError) return } - val, _, _, _, err := s.store.GetKVEntry(constants.PeersKey) + members, err := s.getConsensusMembers() if err != nil { - http.Error(w, "Failed to get peers from KV store", http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - members := make(map[string]state.PeerInfo) - if val != nil { - if err := json.Unmarshal(val, &members); err != nil { - glog.Errorf("Failed to unmarshal peers map: %v", err) - } - } data := MessagesData{ - BaseData: BaseData{ - Title: "Messages", - AgentName: shortName, - ActiveNav: "messages", - }, + BaseData: base, } var ids []string @@ -543,31 +557,21 @@ func (s *HTTPServer) handlePeers(w http.ResponseWriter, r *http.Request) { http.Error(w, "Failed to get Agent ID", http.StatusInternalServerError) return } - shortName, err := s.store.GetShortName() + + base, err := s.prepareBaseData("Peers", "peers") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } - val, _, _, _, err := s.store.GetKVEntry(constants.PeersKey) + members, err := s.getConsensusMembers() if err != nil { - http.Error(w, "Failed to get peers from KV store", http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - members := make(map[string]state.PeerInfo) - if val != nil { - if err := json.Unmarshal(val, &members); err != nil { - glog.Errorf("Failed to unmarshal peers map: %v", err) - } - } - data := PeersData{ - BaseData: BaseData{ - Title: "Peers", - AgentName: shortName, - ActiveNav: "peers", - }, + BaseData: base, } var ids []string @@ -618,11 +622,12 @@ func (s *HTTPServer) handlePeers(w http.ResponseWriter, r *http.Request) { } func (s *HTTPServer) handleStore(w http.ResponseWriter, r *http.Request) { - shortName, err := s.store.GetShortName() + base, err := s.prepareBaseData("KV Store", "store") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } + kvs, err := s.store.GetAllKVs() if err != nil { http.Error(w, "Failed to get KV store", http.StatusInternalServerError) @@ -630,11 +635,7 @@ func (s *HTTPServer) handleStore(w http.ResponseWriter, r *http.Request) { } data := StoreData{ - BaseData: BaseData{ - Title: "KV Store", - AgentName: shortName, - ActiveNav: "store", - }, + BaseData: base, } for _, kv := range kvs { @@ -683,16 +684,16 @@ func (s *HTTPServer) handleCommand(w http.ResponseWriter, r *http.Request) { return } - shortName, _ := s.store.GetShortName() + base, err := s.prepareBaseData("Proposal Success", "") + if err != nil { + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) + return + } data := CommandData{ - BaseData: BaseData{ - Title: "Proposal Success", - AgentName: shortName, - ActiveNav: "", - }, - Key: key, - Value: val, + BaseData: base, + Key: key, + Value: val, } w.Header().Set("Content-Type", "text/html") @@ -703,9 +704,9 @@ func (s *HTTPServer) handleCommand(w http.ResponseWriter, r *http.Request) { } func (s *HTTPServer) handleUserAPI(w http.ResponseWriter, r *http.Request) { - shortName, err := s.store.GetShortName() + base, err := s.prepareBaseData("User API", "userapi") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } @@ -715,11 +716,7 @@ func (s *HTTPServer) handleUserAPI(w http.ResponseWriter, r *http.Request) { s.mu.Unlock() data := UserAPIData{ - BaseData: BaseData{ - Title: "User API", - AgentName: shortName, - ActiveNav: "userapi", - }, + BaseData: base, } ongoingHTML := "" @@ -1263,9 +1260,9 @@ func prototextToTable(text string) string { } func (s *HTTPServer) handleSystem(w http.ResponseWriter, r *http.Request) { - shortName, err := s.store.GetShortName() + base, err := s.prepareBaseData("System Introspection", "system") if err != nil { - http.Error(w, "Failed to get Short Name", http.StatusInternalServerError) + http.Error(w, "Failed to prepare base data", http.StatusInternalServerError) return } @@ -1276,11 +1273,7 @@ func (s *HTTPServer) handleSystem(w http.ResponseWriter, r *http.Request) { numCPU := runtime.NumCPU() data := SystemData{ - BaseData: BaseData{ - Title: "System Introspection", - AgentName: shortName, - ActiveNav: "system", - }, + BaseData: base, NumCPU: numCPU, NumGoroutines: numGoroutines, Alloc: m.Alloc,