func (s *httpServer) nodesHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } producers, _ := lookupd.GetLookupdProducers(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) p := struct { Title string Version string GraphOptions *GraphOptions Producers []*lookupd.Producer Lookupd []string }{ Title: "NSQ Nodes", Version: version.Binary, GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Producers: producers, Lookupd: s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, } err = templates.T.ExecuteTemplate(w, "nodes.html", p) if err != nil { s.ctx.nsqadmin.logf("ERROR: executing template - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } return nil, nil }
func (s *httpServer) graphiteDataHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } metric, err := reqParams.Get("metric") if err != nil || metric != "rate" { return nil, http_api.Err{404, "INVALID_ARG_METRIC"} } target, err := reqParams.Get("target") if err != nil { return nil, http_api.Err{404, "INVALID_ARG_TARGET"} } query := rateQuery(target, s.ctx.nsqadmin.opts.StatsdInterval) url := s.ctx.nsqadmin.opts.GraphiteURL + query s.ctx.nsqadmin.logf("GRAPHITE: %s", url) response, err := graphiteGet(url) if err != nil { s.ctx.nsqadmin.logf("ERROR: graphite request failed - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } resp, err := parseRateResponse(response, s.ctx.nsqadmin.opts.StatsdInterval) if err != nil { s.ctx.nsqadmin.logf("ERROR: response formatting failed - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } w.Header().Set("Content-Type", "application/json") return resp, nil }
func (s *httpServer) doEmptyTopic(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } if !protocol.IsValidTopicName(topicName) { return nil, http_api.Err{400, "INVALID_TOPIC"} } topic, err := s.ctx.nsqd.GetExistingTopic(topicName) if err != nil { return nil, http_api.Err{404, "TOPIC_NOT_FOUND"} } err = topic.Empty() if err != nil { return nil, http_api.Err{500, "INTERNAL_ERROR"} } return nil, nil }
func (s *httpServer) indexHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } var topics []string if len(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) != 0 { topics, _ = lookupd.GetLookupdTopics(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) } else { topics, _ = lookupd.GetNSQDTopics(s.ctx.nsqadmin.opts.NSQDHTTPAddresses) } p := struct { Title string GraphOptions *GraphOptions Topics Topics Version string }{ Title: "NSQ", GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Topics: TopicsFromStrings(topics), Version: version.Binary, } err = templates.T.ExecuteTemplate(w, "index.html", p) if err != nil { s.ctx.nsqadmin.logf("ERROR: executing template - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } return nil, nil }
func (s *httpServer) doDeleteTopic(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } registrations := s.ctx.nsqlookupd.DB.FindRegistrations("channel", topicName, "*") for _, registration := range registrations { s.ctx.nsqlookupd.logf("DB: removing channel(%s) from topic(%s)", registration.SubKey, topicName) s.ctx.nsqlookupd.DB.RemoveRegistration(registration) } registrations = s.ctx.nsqlookupd.DB.FindRegistrations("topic", topicName, "") for _, registration := range registrations { s.ctx.nsqlookupd.logf("DB: removing topic(%s)", topicName) s.ctx.nsqlookupd.DB.RemoveRegistration(registration) } return nil, nil }
func (s *httpServer) doPauseTopic(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } topic, err := s.ctx.nsqd.GetExistingTopic(topicName) if err != nil { return nil, http_api.Err{404, "TOPIC_NOT_FOUND"} } if strings.Contains(req.URL.Path, "unpause") { err = topic.UnPause() } else { err = topic.Pause() } if err != nil { s.ctx.nsqd.logf("ERROR: failure in %s - %s", req.URL.Path, err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } // pro-actively persist metadata so in case of process failure // nsqd won't suddenly (un)pause a topic s.ctx.nsqd.Lock() s.ctx.nsqd.PersistMetadata() s.ctx.nsqd.Unlock() return nil, nil }
func (s *httpServer) doTombstoneTopicProducer(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } node, err := reqParams.Get("node") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_NODE"} } s.ctx.nsqlookupd.logf("DB: setting tombstone for producer@%s of topic(%s)", node, topicName) producers := s.ctx.nsqlookupd.DB.FindProducers("topic", topicName, "") for _, p := range producers { thisNode := fmt.Sprintf("%s:%d", p.peerInfo.BroadcastAddress, p.peerInfo.HTTPPort) if thisNode == node { p.Tombstone() } } return nil, nil }
func (s *httpServer) indexHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } var topics []string if len(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) != 0 { topics, _ = lookupd.GetLookupdTopics(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) } else { topics, _ = lookupd.GetNSQDTopics(s.ctx.nsqadmin.opts.NSQDHTTPAddresses) } p := struct { Title string GraphOptions *GraphOptions Topics Topics Version string }{ Title: "NSQ", GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Topics: TopicsFromStrings(topics), Version: version.Binary, } err = templates.T.ExecuteTemplate(w, "index.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) doLookup(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } registration := s.ctx.nsqlookupd.DB.FindRegistrations("topic", topicName, "") if len(registration) == 0 { return nil, http_api.Err{404, "TOPIC_NOT_FOUND"} } channels := s.ctx.nsqlookupd.DB.FindRegistrations("channel", topicName, "*").SubKeys() producers := s.ctx.nsqlookupd.DB.FindProducers("topic", topicName, "") producers = producers.FilterByActive(s.ctx.nsqlookupd.opts.InactiveProducerTimeout, s.ctx.nsqlookupd.opts.TombstoneLifetime) return map[string]interface{}{ "channels": channels, "producers": producers.PeerInfo(), }, nil }
func (s *httpServer) nodesHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } producers, _ := lookupd.GetLookupdProducers(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) p := struct { Title string Version string GraphOptions *GraphOptions Producers []*lookupd.Producer Lookupd []string }{ Title: "NSQ Nodes", Version: version.Binary, GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Producers: producers, Lookupd: s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, } err = templates.T.ExecuteTemplate(w, "nodes.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) doPauseTopic(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } topic, err := s.ctx.nsqd.GetExistingTopic(topicName) if err != nil { return nil, http_api.Err{404, "TOPIC_NOT_FOUND"} } if strings.Contains(req.URL.Path, "unpause") { err = topic.UnPause() } else { err = topic.Pause() } if err != nil { s.ctx.nsqd.logf("ERROR: failure in %s - %s", req.URL.Path, err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } return nil, nil }
func (s *httpServer) channelHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { topicName := ps.ByName("topic") channelName := ps.ByName("channel") reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } producers := s.getProducers(topicName) _, allChannelStats, _ := lookupd.GetNSQDStats(producers, topicName) channelStats, ok := allChannelStats[channelName] if !ok { s.ctx.nsqadmin.logf("ERROR: channel stats do not exist") http.Error(w, "INVALID_REQUEST", 500) return } hasE2eLatency := channelStats.E2eProcessingLatency != nil && len(channelStats.E2eProcessingLatency.Percentiles) > 0 var firstHost *lookupd.ChannelStats if len(channelStats.HostStats) > 0 { firstHost = channelStats.HostStats[0] } p := struct { Title string GraphOptions *GraphOptions Version string Topic string Channel string TopicProducers []string ChannelStats *lookupd.ChannelStats FirstHost *lookupd.ChannelStats HasE2eLatency bool }{ Title: fmt.Sprintf("NSQ %s / %s", topicName, channelName), GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Version: version.Binary, Topic: topicName, Channel: channelName, TopicProducers: producers, ChannelStats: channelStats, FirstHost: firstHost, HasE2eLatency: hasE2eLatency, } err = templates.T.ExecuteTemplate(w, "channel.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) graphiteDataHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } metric, err := reqParams.Get("metric") if err != nil { s.ctx.nsqadmin.logf("ERROR: missing metric param - %s", err) http.Error(w, "MISSING_METRIC_PARAM", 500) return } target, err := reqParams.Get("target") if err != nil { s.ctx.nsqadmin.logf("ERROR: missing target param - %s", err) http.Error(w, "MISSING_TARGET_PARAM", 500) return } var queryFunc func(string) string var formatJSONResponseFunc func([]byte) ([]byte, error) switch metric { case "rate": queryFunc = rateQuery formatJSONResponseFunc = parseRateResponse default: s.ctx.nsqadmin.logf("ERROR: unknown metric value %s", metric) http.Error(w, "INVALID_METRIC_PARAM", 500) return } query := queryFunc(target) url := s.ctx.nsqadmin.opts.GraphiteURL + query s.ctx.nsqadmin.logf("GRAPHITE: %s", url) response, err := graphiteGet(url) if err != nil { s.ctx.nsqadmin.logf("ERROR: graphite request failed %s", err) http.Error(w, "GRAPHITE_FAILED", 500) return } resp, err := formatJSONResponseFunc(response) if err != nil { s.ctx.nsqadmin.logf("ERROR: response formating failed - %s", err) http.Error(w, "INVALID_GRAPHITE_RESPONSE", 500) return } w.Header().Set("Content-Type", "application/json") w.Write(resp) return }
func (s *httpServer) topicHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { topicName := ps.ByName("topic") reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } producers := s.getProducers(topicName) topicStats, channelStats, _ := lookupd.GetNSQDStats(producers, topicName) globalTopicStats := &lookupd.TopicStats{HostAddress: "Total"} for _, t := range topicStats { globalTopicStats.Add(t) } hasE2eLatency := globalTopicStats.E2eProcessingLatency != nil && len(globalTopicStats.E2eProcessingLatency.Percentiles) > 0 var firstTopic *lookupd.TopicStats if len(topicStats) > 0 { firstTopic = topicStats[0] } p := struct { Title string GraphOptions *GraphOptions Version string Topic string TopicProducers []string TopicStats []*lookupd.TopicStats FirstTopic *lookupd.TopicStats GlobalTopicStats *lookupd.TopicStats ChannelStats map[string]*lookupd.ChannelStats HasE2eLatency bool }{ Title: fmt.Sprintf("NSQ %s", topicName), GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Version: version.Binary, Topic: topicName, TopicProducers: producers, TopicStats: topicStats, FirstTopic: firstTopic, GlobalTopicStats: globalTopicStats, ChannelStats: channelStats, HasE2eLatency: hasE2eLatency, } err = templates.T.ExecuteTemplate(w, "topic.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) doStats(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } formatString, _ := reqParams.Get("format") topicName, _ := reqParams.Get("topic") channelName, _ := reqParams.Get("channel") jsonFormat := formatString == "json" stats := s.ctx.nsqd.GetStats() health := s.ctx.nsqd.GetHealth() startTime := s.ctx.nsqd.GetStartTime() uptime := time.Since(startTime) // If we WERE given a topic-name, remove stats for all the other topics: if len(topicName) > 0 { // Find the desired-topic-index: for _, topicStats := range stats { if topicStats.TopicName == topicName { // If we WERE given a channel-name, remove stats for all the other channels: if len(channelName) > 0 { // Find the desired-channel: for _, channelStats := range topicStats.Channels { if channelStats.ChannelName == channelName { topicStats.Channels = []ChannelStats{channelStats} // We've got the channel we were looking for: break } } } // We've got the topic we were looking for: stats = []TopicStats{topicStats} break } } } if !jsonFormat { return s.printStats(stats, health, startTime, uptime), nil } return struct { Version string `json:"version"` Health string `json:"health"` StartTime int64 `json:"start_time"` Topics []TopicStats `json:"topics"` }{version.Binary, health, startTime.Unix(), stats}, nil }
// this endpoint works by giving out an ID that maps to a stats dictionary // The initial request is the number of messages processed since each nsqd started up. // Subsequent requsts pass that ID and get an updated delta based on each individual channel/nsqd message count // That ID must be re-requested or it will be expired. func (s *httpServer) counterDataHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http_api.Respond(w, 500, "INVALID_REQUEST", nil) return } statsID, _ := reqParams.Get("id") now := time.Now() if statsID == "" { // make a new one statsID = fmt.Sprintf("%d.%d", now.Unix(), now.UnixNano()) } stats, ok := s.counters[statsID] if !ok { stats = make(map[string]int64) } newStats := make(map[string]int64) newStats["time"] = now.Unix() producers, _ := lookupd.GetLookupdProducers(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) addresses := make([]string, len(producers)) for i, p := range producers { addresses[i] = p.HTTPAddress() } _, channelStats, _ := lookupd.GetNSQDStats(addresses, "") var newMessages int64 var totalMessages int64 for _, channelStats := range channelStats { for _, hostChannelStats := range channelStats.HostStats { key := fmt.Sprintf("%s:%s:%s", channelStats.TopicName, channelStats.ChannelName, hostChannelStats.HostAddress) d, ok := stats[key] if ok && d <= hostChannelStats.MessageCount { newMessages += (hostChannelStats.MessageCount - d) } totalMessages += hostChannelStats.MessageCount newStats[key] = hostChannelStats.MessageCount } } s.counters[statsID] = newStats data := make(map[string]interface{}) data["new_messages"] = newMessages data["total_messages"] = totalMessages data["id"] = statsID http_api.Respond(w, 200, "OK", data) }
func (s *httpServer) graphiteDataHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } metric, err := reqParams.Get("metric") if err != nil { s.ctx.nsqadmin.logf("ERROR: missing metric param - %s", err) http.Error(w, "MISSING_METRIC_PARAM", 500) return } target, err := reqParams.Get("target") if err != nil { s.ctx.nsqadmin.logf("ERROR: missing target param - %s", err) http.Error(w, "MISSING_TARGET_PARAM", 500) return } if metric != "rate" { s.ctx.nsqadmin.logf("ERROR: unknown metric value %s", metric) http.Error(w, "INVALID_METRIC_PARAM", 500) return } query := rateQuery(target, s.ctx.nsqadmin.opts.StatsdInterval) url := s.ctx.nsqadmin.opts.GraphiteURL + query s.ctx.nsqadmin.logf("GRAPHITE: %s", url) response, err := graphiteGet(url) if err != nil { s.ctx.nsqadmin.logf("ERROR: graphite request failed %s", err) http.Error(w, "GRAPHITE_FAILED", 500) return } resp, err := parseRateResponse(response, s.ctx.nsqadmin.opts.StatsdInterval) if err != nil { s.ctx.nsqadmin.logf("ERROR: response formating failed - %s", err) http.Error(w, "INVALID_GRAPHITE_RESPONSE", 500) return } w.Header().Set("Content-Type", "application/json") w.Write(resp) return }
// this endpoint works by giving out an ID that maps to a stats dictionary // The initial request is the number of messages processed since each nsqd started up. // Subsequent requsts pass that ID and get an updated delta based on each individual channel/nsqd message count // That ID must be re-requested or it will be expired. func (s *httpServer) counterDataHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } statsID, _ := reqParams.Get("id") now := time.Now() if statsID == "" { // make a new one statsID = fmt.Sprintf("%d.%d", now.Unix(), now.UnixNano()) } stats, ok := s.counters[statsID] if !ok { stats = make(map[string]int64) } newStats := make(map[string]int64) newStats["time"] = now.Unix() producers, _ := lookupd.GetLookupdProducers(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) addresses := make([]string, len(producers)) for i, p := range producers { addresses[i] = p.HTTPAddress() } _, channelStats, _ := lookupd.GetNSQDStats(addresses, "") var newMessages int64 var totalMessages int64 for _, channelStats := range channelStats { for _, hostChannelStats := range channelStats.HostStats { key := fmt.Sprintf("%s:%s:%s", channelStats.TopicName, channelStats.ChannelName, hostChannelStats.HostAddress) d, ok := stats[key] if ok && d <= hostChannelStats.MessageCount { newMessages += (hostChannelStats.MessageCount - d) } totalMessages += hostChannelStats.MessageCount newStats[key] = hostChannelStats.MessageCount } } s.counters[statsID] = newStats return struct { NewMessages int64 `json:"new_messages"` TotalMessages int64 `json:"total_messages"` ID string `json:"id"` }{newMessages, totalMessages, statsID}, nil }
func (s *httpServer) graphiteHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } metric, err := reqParams.Get("metric") if err != nil || metric != "rate" { return nil, http_api.Err{404, "INVALID_ARG_METRIC"} } target, err := reqParams.Get("target") if err != nil { return nil, http_api.Err{404, "INVALID_ARG_TARGET"} } params := url.Values{} params.Set("from", fmt.Sprintf("-%dsec", s.ctx.nsqadmin.opts.StatsdInterval*2/time.Second)) params.Set("until", fmt.Sprintf("-%dsec", s.ctx.nsqadmin.opts.StatsdInterval/time.Second)) params.Set("format", "json") params.Set("target", target) query := fmt.Sprintf("/render?%s", params.Encode()) url := s.ctx.nsqadmin.opts.GraphiteURL + query s.ctx.nsqadmin.logf("GRAPHITE: %s", url) var response []struct { Target string `json:"target"` DataPoints [][]*float64 `json:"datapoints"` } err = http_api.GETV1(url, &response) if err != nil { s.ctx.nsqadmin.logf("ERROR: graphite request failed - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } var rateStr string rate := *response[0].DataPoints[0][0] if rate < 0 { rateStr = "N/A" } else { rateDivisor := s.ctx.nsqadmin.opts.StatsdInterval / time.Second rateStr = fmt.Sprintf("%.2f", rate/float64(rateDivisor)) } return struct { Rate string `json:"rate"` }{rateStr}, nil }
func (s *httpServer) doChannels(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } channels := s.ctx.nsqlookupd.DB.FindRegistrations("channel", topicName, "*").SubKeys() return map[string]interface{}{ "channels": channels, }, nil }
func (s *httpServer) doDeleteTopic(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } err = s.ctx.nsqd.DeleteExistingTopic(topicName) if err != nil { return nil, http_api.Err{404, "TOPIC_NOT_FOUND"} } return nil, nil }
func (s *httpServer) getExistingTopicFromQuery(req *http.Request) (*http_api.ReqParams, *Topic, string, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, nil, "", http_api.Err{400, "INVALID_REQUEST"} } topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams) if err != nil { return nil, nil, "", http_api.Err{400, err.Error()} } topic, err := s.ctx.nsqd.GetExistingTopic(topicName) if err != nil { return nil, nil, "", http_api.Err{404, "TOPIC_NOT_FOUND"} } return reqParams, topic, channelName, err }
func (s *httpServer) doCreateTopic(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, err := reqParams.Get("topic") if err != nil { return nil, http_api.Err{400, "MISSING_ARG_TOPIC"} } if !protocol.IsValidTopicName(topicName) { return nil, http_api.Err{400, "INVALID_ARG_TOPIC"} } s.ctx.nsqlookupd.logf("DB: adding topic(%s)", topicName) key := Registration{"topic", topicName, ""} s.ctx.nsqlookupd.DB.AddRegistration(key) return nil, nil }
func (s *httpServer) doCreateChannel(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams) if err != nil { return nil, http_api.Err{400, err.Error()} } s.ctx.nsqlookupd.logf("DB: adding channel(%s) in topic(%s)", channelName, topicName) key := Registration{"channel", topicName, channelName} s.ctx.nsqlookupd.DB.AddRegistration(key) s.ctx.nsqlookupd.logf("DB: adding topic(%s)", topicName) key = Registration{"topic", topicName, ""} s.ctx.nsqlookupd.DB.AddRegistration(key) return nil, nil }
func (s *httpServer) lookupHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } channels := make(map[string][]string) allTopics, _ := lookupd.GetLookupdTopics(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) for _, topicName := range allTopics { var producers []string producers, _ = lookupd.GetLookupdTopicProducers(topicName, s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) if len(producers) == 0 { topicChannels, _ := lookupd.GetLookupdTopicChannels(topicName, s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) channels[topicName] = topicChannels } } p := struct { Title string GraphOptions *GraphOptions TopicMap map[string][]string Lookupd []string Version string }{ Title: "NSQ Lookup", GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), TopicMap: channels, Lookupd: s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, Version: version.Binary, } err = templates.T.ExecuteTemplate(w, "lookup.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) doTopics(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, err.Error()} } var topics []string if len(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) != 0 { topics, _ = s.ci.GetLookupdTopics(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) } else { topics, _ = s.ci.GetNSQDTopics(s.ctx.nsqadmin.opts.NSQDHTTPAddresses) } inactive, _ := reqParams.Get("inactive") if inactive == "true" { topicChannelMap := make(map[string][]string) if len(s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) == 0 { goto respond } for _, topicName := range topics { producerList, _ := s.ci.GetLookupdTopicProducers( topicName, s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) if len(producerList) == 0 { topicChannels, _ := s.ci.GetLookupdTopicChannels( topicName, s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) topicChannelMap[topicName] = topicChannels } } respond: return struct { Topics map[string][]string `json:"topics"` }{topicChannelMap}, nil } return struct { Topics []string `json:"topics"` }{topics}, nil }
func (s *httpServer) doDeleteChannel(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams) if err != nil { return nil, http_api.Err{400, err.Error()} } registrations := s.ctx.nsqlookupd.DB.FindRegistrations("channel", topicName, channelName) if len(registrations) == 0 { return nil, http_api.Err{404, "CHANNEL_NOT_FOUND"} } s.ctx.nsqlookupd.logf("DB: removing channel(%s) from topic(%s)", channelName, topicName) for _, registration := range registrations { s.ctx.nsqlookupd.DB.RemoveRegistration(registration) } return nil, nil }
func (s *httpServer) counterHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { return nil, http_api.Err{400, "INVALID_REQUEST"} } p := struct { Title string Version string GraphOptions *GraphOptions Target counterTarget }{ Title: "NSQ Message Counts", Version: version.Binary, GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Target: counterTarget{}, } err = templates.T.ExecuteTemplate(w, "counter.html", p) if err != nil { s.ctx.nsqadmin.logf("ERROR: executing template - %s", err) return nil, http_api.Err{500, "INTERNAL_ERROR"} } return nil, nil }
func (s *httpServer) counterHandler(w http.ResponseWriter, req *http.Request) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to parse request params - %s", err) http.Error(w, "INVALID_REQUEST", 500) return } p := struct { Title string Version string GraphOptions *GraphOptions Target counterTarget }{ Title: "NSQ Message Counts", Version: version.Binary, GraphOptions: NewGraphOptions(w, req, reqParams, s.ctx), Target: counterTarget{}, } err = templates.T.ExecuteTemplate(w, "counter.html", p) if err != nil { s.ctx.nsqadmin.logf("Template Error %s", err) http.Error(w, "Template Error", 500) } }
func (s *httpServer) doStats(req *http.Request) (interface{}, error) { reqParams, err := http_api.NewReqParams(req) if err != nil { s.ctx.nsqd.logf("ERROR: failed to parse request params - %s", err) return nil, http_api.Err{400, "INVALID_REQUEST"} } formatString, _ := reqParams.Get("format") jsonFormat := formatString == "json" stats := s.ctx.nsqd.GetStats() health := s.ctx.nsqd.GetHealth() startTime := s.ctx.nsqd.GetStartTime() uptime := time.Since(startTime) if !jsonFormat { return s.printStats(stats, health, startTime, uptime), nil } return struct { Version string `json:"version"` Health string `json:"health"` StartTime int64 `json:"start_time"` Topics []TopicStats `json:"topics"` }{version.Binary, health, startTime.Unix(), stats}, nil }