Пример #1
0
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)
}
Пример #2
0
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)
}
Пример #3
0
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)
}
Пример #4
0
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)
}
Пример #5
0
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)
}
Пример #6
0
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)
}
Пример #7
0
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)
}
Пример #8
0
// 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
}
Пример #9
0
// toStrings converts a set into a slice of strings
func toStrings(s set.Interface) []string {
	l := set.StringSlice(s)
	sort.Strings(l)
	return l
}
Пример #10
0
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
}