func (h *NsSearchResultRedirct) ServeHTTP( w http.ResponseWriter, req *http.Request) { allPlanPIndexes, _, err := h.mgr.GetPlanPIndexes(false) if err != nil { rest.ShowError(w, req, fmt.Sprintf("could not get plan pindexes: %v", err), 500) return } pIndexName := mux.Vars(req)["pIndexName"] planPIndex, ok := allPlanPIndexes.PlanPIndexes[pIndexName] if !ok { rest.ShowError(w, req, fmt.Sprintf("no pindex named: %s", pIndexName), 400) return } docID := mux.Vars(req)["docID"] source := planPIndex.SourceName http.Redirect(w, req, "/ui/index.html#/documents/"+docID+"?documentsBucket="+source, http.StatusMovedPermanently) }
func (h *NsStatusHandler) ServeHTTP( w http.ResponseWriter, req *http.Request) { initNsServerCaching(h.mgr) rd := <-recentInfoCh if rd.err != nil { rest.ShowError(w, req, fmt.Sprintf("could not retrieve defs: %v", rd.err), 500) return } indexDefsMap := rd.indexDefsMap nodeDefs := rd.nodeDefs planPIndexes := rd.planPIndexes w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Write(cbgt.JsonOpenBrace) w.Write(statsNamePrefix) w.Write([]byte("status")) w.Write(statsNameSuffix) w.Write([]byte("[")) indexDefNames := make(sort.StringSlice, 0, len(indexDefsMap)) for indexDefName := range indexDefsMap { indexDefNames = append(indexDefNames, indexDefName) } sort.Sort(indexDefNames) for i, indexDefName := range indexDefNames { indexDef := indexDefsMap[indexDefName] if i > 0 { w.Write(cbgt.JsonComma) } rest.MustEncode(w, struct { Hosts []string `json:"hosts"` Bucket string `json:"bucket"` Name string `json:"name"` }{ Bucket: indexDef.SourceName, Name: indexDefName, Hosts: NsHostsForIndex(indexDefName, planPIndexes, nodeDefs), }) } w.Write([]byte("],")) w.Write(statsNamePrefix) w.Write([]byte("code")) w.Write(statsNameSuffix) w.Write([]byte("\"success\"")) w.Write(cbgt.JsonCloseBrace) }
func (h *NsStatsHandler) ServeHTTP( w http.ResponseWriter, req *http.Request) { _, indexDefsMap, err := h.mgr.GetIndexDefs(false) if err != nil { rest.ShowError(w, req, "could not retrieve index defs", 500) return } nsIndexStats := make(NSIndexStats, len(indexDefsMap)) for indexDefName, indexDef := range indexDefsMap { nsIndexStats[indexDef.SourceName+":"+indexDefName] = NewIndexStat() } feeds, pindexes := h.mgr.CurrentMaps() sourceName := "" for _, pindex := range pindexes { sourceName = pindex.SourceName lindexName := pindex.SourceName + ":" + pindex.IndexName nsIndexStat, ok := nsIndexStats[lindexName] if ok { // manually track a statistic representing // the number of pindex in the index oldValue, ok := nsIndexStat["num_pindexes"] if ok { switch oldValue := oldValue.(type) { case float64: oldValue += float64(1) nsIndexStat["num_pindexes"] = oldValue } } // automatically process all the pindex dest stats err := addPindexStats(pindex, nsIndexStat) if err != nil { rest.ShowError(w, req, fmt.Sprintf("error processing PIndex stats: %v", err), 500) return } } } for _, feed := range feeds { lindexName := sourceName + ":" + feed.IndexName() nsIndexStat, ok := nsIndexStats[lindexName] if ok { err := addFeedStats(feed, nsIndexStat) // automatically process all the feed stats if err != nil { rest.ShowError(w, req, fmt.Sprintf("error processing Feed stats: %v", err), 500) return } } } // FIXME hard-coded top-level stats nsIndexStats[""] = make(map[string]interface{}) nsIndexStats[""]["num_connections"] = 0 nsIndexStats[""]["needs_restart"] = false rest.MustEncode(w, nsIndexStats) }
func (h *NsStatusHandler) ServeHTTP( w http.ResponseWriter, req *http.Request) { cfg := h.mgr.Cfg() planPIndexes, _, err := cbgt.CfgGetPlanPIndexes(cfg) if err != nil { rest.ShowError(w, req, "could not retrieve plan pIndexes", 500) return } nodesDefs, _, err := cbgt.CfgGetNodeDefs(cfg, cbgt.NODE_DEFS_WANTED) if err != nil { rest.ShowError(w, req, "could not retrieve node defs (wanted)", 500) return } _, indexDefsMap, err := h.mgr.GetIndexDefs(false) if err != nil { rest.ShowError(w, req, "could not retrieve index defs", 500) return } w.Write(cbgt.JsonOpenBrace) w.Write(statsNamePrefix) w.Write([]byte("status")) w.Write(statsNameSuffix) w.Write([]byte("[")) indexDefNames := make(sort.StringSlice, 0, len(indexDefsMap)) for indexDefName := range indexDefsMap { indexDefNames = append(indexDefNames, indexDefName) } sort.Sort(indexDefNames) for i, indexDefName := range indexDefNames { indexDef := indexDefsMap[indexDefName] if i > 0 { w.Write(cbgt.JsonComma) } rest.MustEncode(w, struct { Completion int `json:"completion"` Hosts []string `json:"hosts"` Status string `json:"status"` Bucket string `json:"bucket"` Name string `json:"name"` }{ Bucket: indexDef.SourceName, Name: indexDefName, Hosts: HostsForIndex(indexDefName, planPIndexes, nodesDefs), // FIXME hard-coded Completion: 100, Status: "Ready", }) } w.Write([]byte("],")) w.Write(statsNamePrefix) w.Write([]byte("code")) w.Write(statsNameSuffix) w.Write([]byte("\"success\"")) w.Write(cbgt.JsonCloseBrace) }
func (h *NsStatsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { currentStatsCount := atomic.AddInt64(&h.statsCount, 1) initNsServerCaching(h.mgr) rd := <-recentInfoCh if rd.err != nil { rest.ShowError(w, req, fmt.Sprintf("could not retrieve defs: %v", rd.err), 500) return } indexDefsMap := rd.indexDefsMap planPIndexes := rd.planPIndexes nodeUUID := h.mgr.UUID() nsIndexStats := make(NSIndexStats, len(indexDefsMap)) indexNameToSourceName := map[string]string{} indexNameToPlanPIndexes := map[string][]*cbgt.PlanPIndex{} if planPIndexes != nil { for _, planPIndex := range planPIndexes.PlanPIndexes { // Only focus on the planPIndex entries for this node. if planPIndex.Nodes[nodeUUID] != nil { indexNameToPlanPIndexes[planPIndex.IndexName] = append(indexNameToPlanPIndexes[planPIndex.IndexName], planPIndex) } } } indexQueryPathStats := MapRESTPathStats[RESTIndexQueryPath] // Keyed by indexName, sub-key is source partition id. indexNameToSourcePartitionSeqs := map[string]map[string]cbgt.UUIDSeq{} // Keyed by indexName, sub-key is source partition id. indexNameToDestPartitionSeqs := map[string]map[string]cbgt.UUIDSeq{} for indexName, indexDef := range indexDefsMap { nsIndexStat := NewIndexStat() nsIndexStats[indexDef.SourceName+":"+indexName] = nsIndexStat indexNameToSourceName[indexName] = indexDef.SourceName focusStats := indexQueryPathStats.FocusStats(indexName) if focusStats != nil { totalQueries := atomic.LoadUint64(&focusStats.TotRequest) nsIndexStat["total_queries"] = totalQueries if totalQueries > 0 { nsIndexStat["avg_queries_latency"] = float64((atomic.LoadUint64(&focusStats.TotRequestTimeNS) / totalQueries)) / 1000000.0 // Convert from nanosecs to millisecs. } nsIndexStat["total_request_time"] = atomic.LoadUint64(&focusStats.TotRequestTimeNS) nsIndexStat["total_queries_slow"] = atomic.LoadUint64(&focusStats.TotRequestSlow) nsIndexStat["total_queries_timeout"] = atomic.LoadUint64(&focusStats.TotRequestTimeout) nsIndexStat["total_queries_error"] = atomic.LoadUint64(&focusStats.TotRequestErr) nsIndexStat["total_bytes_query_results"] = atomic.LoadUint64(&focusStats.TotResponseBytes) nsIndexStat["num_pindexes_target"] = uint64(len(indexNameToPlanPIndexes[indexName])) } feedType, exists := cbgt.FeedTypes[indexDef.SourceType] if !exists || feedType == nil || feedType.PartitionSeqs == nil { continue } partitionSeqs := GetSourcePartitionSeqs(SourceSpec{ SourceType: indexDef.SourceType, SourceName: indexDef.SourceName, SourceUUID: indexDef.SourceUUID, SourceParams: indexDef.SourceParams, Server: h.mgr.Server(), }) if partitionSeqs != nil { indexNameToSourcePartitionSeqs[indexName] = partitionSeqs } } feeds, pindexes := h.mgr.CurrentMaps() for _, pindex := range pindexes { nsIndexName := pindex.SourceName + ":" + pindex.IndexName nsIndexStat, ok := nsIndexStats[nsIndexName] if ok { // manually track num pindexes oldValue, ok := nsIndexStat["num_pindexes_actual"] if ok { switch oldValue := oldValue.(type) { case float64: oldValue += float64(1) nsIndexStat["num_pindexes_actual"] = oldValue // TODO: Former name was num_pindexes, need to remove one day. nsIndexStat["num_pindexes"] = oldValue } } // automatically process all the pindex dest stats err := addPIndexStats(pindex, nsIndexStat) if err != nil { rest.ShowError(w, req, fmt.Sprintf("error processing PIndex stats: %v", err), 500) return } dest := pindex.Dest if dest != nil { destForwarder, ok := dest.(*cbgt.DestForwarder) if !ok { continue } partitionSeqsProvider, ok := destForwarder.DestProvider.(PartitionSeqsProvider) if !ok { continue } partitionSeqs, err := partitionSeqsProvider.PartitionSeqs() if err == nil { m := indexNameToDestPartitionSeqs[pindex.IndexName] if m == nil { m = map[string]cbgt.UUIDSeq{} indexNameToDestPartitionSeqs[pindex.IndexName] = m } for partitionId, uuidSeq := range partitionSeqs { m[partitionId] = uuidSeq } } } } } for _, feed := range feeds { sourceName := indexNameToSourceName[feed.IndexName()] nsIndexName := sourceName + ":" + feed.IndexName() nsIndexStat, ok := nsIndexStats[nsIndexName] if ok { // automatically process all the feed stats err := addFeedStats(feed, nsIndexStat) if err != nil { rest.ShowError(w, req, fmt.Sprintf("error processing Feed stats: %v", err), 500) return } } } for indexName, indexDef := range indexDefsMap { nsIndexStat, ok := nsIndexStats[indexDef.SourceName+":"+indexName] if ok { src := indexNameToSourcePartitionSeqs[indexName] if src == nil { continue } dst := indexNameToDestPartitionSeqs[indexName] if dst == nil { continue } var totSeq uint64 var curSeq uint64 for partitionId, dstUUIDSeq := range dst { srcUUIDSeq, exists := src[partitionId] if exists { totSeq += srcUUIDSeq.Seq curSeq += dstUUIDSeq.Seq } } nsIndexStat["num_mutations_to_index"] = totSeq - curSeq } } topLevelStats := map[string]interface{}{} topLevelStats["num_bytes_used_ram"] = rd.memStats.Alloc topLevelStats["total_gc"] = rd.memStats.NumGC topLevelStats["pct_cpu_gc"] = rd.memStats.GCCPUFraction nsIndexStats[""] = topLevelStats if LogEveryNStats != 0 && currentStatsCount%int64(LogEveryNStats) == 0 { go func() { var buf bytes.Buffer err := rest.WriteManagerStatsJSON(h.mgr, &buf, "") if err != nil { log.Printf("error formatting managerStatsJSON for logs: %v", err) } else { log.Printf("managerStats: %s", buf.String()) } statsJSON, err := json.MarshalIndent(nsIndexStats, "", " ") if err != nil { log.Printf("error formatting JSON for logs: %v", err) return } log.Printf("stats: %s", string(statsJSON)) }() } rest.MustEncode(w, nsIndexStats) }