func (server *Server) serveOriginList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if request.FormValue("filter") == "" || utils.FilterMatch(request.FormValue("filter"), origin.Name) { originSet.Add(origin.Name) } } response := &listResponse{ list: StringListResponse(set.StringSlice(originSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) serveSource(writer http.ResponseWriter, request *http.Request) { name := routeTrimPrefix(request.URL.Path, urlCatalogPath+"sources") if name == "" { server.serveSourceList(writer, request) return } else if response, status := server.parseShowRequest(writer, request); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if origin.SourceExists(name) { originSet.Add(origin.Name) } } if originSet.Size() == 0 { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } origins := set.StringSlice(originSet) sort.Strings(origins) response := SourceResponse{ Name: name, Origins: origins, } server.serveResponse(writer, response, http.StatusOK) }
func (server *Server) serveMetricList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originName := request.FormValue("origin") sourceName := request.FormValue("source") sourceSet := set.New(set.ThreadSafe) if strings.HasPrefix(sourceName, library.LibraryGroupPrefix) { for _, entryName := range server.Library.ExpandSourceGroup( strings.TrimPrefix(sourceName, library.LibraryGroupPrefix), ) { sourceSet.Add(entryName) } } else if sourceName != "" { sourceSet.Add(sourceName) } metricSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if originName != "" && origin.Name != originName { continue } for _, source := range origin.GetSources() { if sourceName != "" && sourceSet.IsEmpty() || !sourceSet.IsEmpty() && !sourceSet.Has(source.Name) { continue } for _, metric := range source.GetMetrics() { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), metric.Name) { continue } metricSet.Add(metric.Name) } } } response := &listResponse{ list: StringListResponse(set.StringSlice(metricSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) serveMetric(writer http.ResponseWriter, request *http.Request) { metricName := routeTrimPrefix(request.URL.Path, urlCatalogPath+"metrics") if metricName == "" { server.serveMetricList(writer, request) return } else if response, status := server.parseShowRequest(writer, request); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) sourceSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { for _, source := range origin.GetSources() { if source.MetricExists(metricName) { originSet.Add(origin.Name) sourceSet.Add(source.Name) } } } if originSet.Size() == 0 { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } origins := set.StringSlice(originSet) sort.Strings(origins) sources := set.StringSlice(sourceSet) sort.Strings(sources) response := MetricResponse{ Name: metricName, Origins: origins, Sources: sources, } server.serveResponse(writer, response, http.StatusOK) }
func (s *Server) handleAPIHosts(c *gin.Context) { hs := set.New(set.ThreadSafe) // Get hosts list hosts, _ := s.poller.GetHosts() for _, h := range hosts { hs.Add(h.Name) } // Get unique set of hosts names result := set.StringSlice(hs) sort.Strings(result) c.Header("Cache-Control", "private, max-age=0") c.JSON(http.StatusOK, result) }
func (s *Server) handleAPIGroups(c *gin.Context) { gs := set.New(set.ThreadSafe) // Get unique sets of groups names hosts, _ := s.poller.GetHosts() for _, h := range hosts { for _, g := range h.Groups { gs.Add(g) } for _, s := range h.Services { for _, g := range s.Groups { gs.Add(g) } } } result := set.StringSlice(gs) natsort.Sort(result) c.Header("Cache-Control", "private, max-age=0") c.JSON(http.StatusOK, result) }
func (server *Server) serveSourceList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originName := request.FormValue("origin") sourceSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if originName != "" && origin.Name != originName { continue } for _, source := range origin.GetSources() { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), source.Name) { continue } sourceSet.Add(source.Name) } } response := &listResponse{ list: StringListResponse(set.StringSlice(sourceSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
// Refresh triggers a full connector data update. func (c *RRDConnector) Refresh(originName string, outputChan chan<- *catalog.Record) error { // Search for files and parse their path for source/metric pairs walkFunc := func(filePath string, fileInfo os.FileInfo, err error) error { var sourceName, metricName string // Report errors if err != nil { logger.Log(logger.LevelWarning, "connector", "rrd[%s]: error while walking: %s", c.name, err) return nil } // Skip non-files mode := fileInfo.Mode() & os.ModeType if mode != 0 { return nil } // Get pattern matches m, err := matchSeriesPattern(c.re, strings.TrimPrefix(filePath, c.path+"/")) if err != nil { logger.Log(logger.LevelInfo, "connector", "rrd[%s]: file `%s' does not match pattern, ignoring", c.name, filePath) return nil } sourceName, metricName = m[0], m[1] if _, ok := c.metrics[sourceName]; !ok { c.metrics[sourceName] = make(map[string]*rrdMetric) } // Extract metric information from .rrd file info, err := rrd.Info(filePath) if err != nil { logger.Log(logger.LevelWarning, "connector", "rrd[%s]: %s", c.name, err) return nil } // Extract consolidation functions list cfSet := set.New(set.ThreadSafe) if cf, ok := info["rra.cf"].([]interface{}); ok { for _, entry := range cf { if name, ok := entry.(string); ok { cfSet.Add(name) } } } cfList := set.StringSlice(cfSet) if _, ok := info["ds.index"]; ok { indexes, ok := info["ds.index"].(map[string]interface{}) if !ok { return nil } for dsName := range indexes { for _, cfName := range cfList { metricFullName := metricName + "/" + dsName + "/" + strings.ToLower(cfName) c.metrics[sourceName][metricFullName] = &rrdMetric{ Dataset: dsName, FilePath: filePath, Step: time.Duration(info["step"].(uint)) * time.Second, Cf: cfName, } outputChan <- &catalog.Record{ Origin: originName, Source: sourceName, Metric: metricFullName, Connector: c, } } } } return nil } if err := utils.WalkDir(c.path, walkFunc); err != nil { return err } return nil }
// toStrings converts a set into a slice of strings func toStrings(s set.Interface) []string { l := set.StringSlice(s) sort.Strings(l) return l }
func (library *Library) expandGroup(name string, groupType int, sourceName string) []string { item, err := library.GetItemByName(name, groupType) if err != nil { logger.Log(logger.LevelError, "library", "expand group: unknown group `%s': %s", name, err) return []string{} } // Launch expansion goroutine itemSet := set.New(set.ThreadSafe) itemChan := make(chan [2]string) itemWg := &sync.WaitGroup{} go func(itemSet set.Interface, itemChan chan [2]string, itemWg *sync.WaitGroup) { var re *regexp.Regexp itemWg.Add(1) for entry := range itemChan { if strings.HasPrefix(entry[0], LibraryMatchPrefixGlob) { if ok, _ := path.Match(strings.TrimPrefix(entry[0], LibraryMatchPrefixGlob), entry[1]); !ok { continue } } else if strings.HasPrefix(entry[0], LibraryMatchPrefixRegexp) { re = regexp.MustCompile(strings.TrimPrefix(entry[0], LibraryMatchPrefixRegexp)) if !re.MatchString(entry[1]) { continue } } else if entry[0] != entry[1] { continue } itemSet.Add(entry[1]) } itemWg.Done() }(itemSet, itemChan, itemWg) // Parse group entries for patterns group := item.(*Group) for _, entry := range group.Entries { if groupType == LibraryItemSourceGroup { origin, err := library.Catalog.GetOrigin(entry.Origin) if err != nil { logger.Log(logger.LevelError, "library", "%s", err) continue } for _, source := range origin.GetSources() { itemChan <- [2]string{entry.Pattern, source.Name} } } else { source, err := library.Catalog.GetSource(entry.Origin, sourceName) if err != nil { logger.Log(logger.LevelError, "library", "%s", err) continue } for _, metric := range source.GetMetrics() { itemChan <- [2]string{entry.Pattern, metric.Name} } } } close(itemChan) itemWg.Wait() result := set.StringSlice(itemSet) sort.Strings(result) return result }