Exemplo n.º 1
1
// Load loads the configuration from the filesystem.
func (config *Config) Load(filePath string) error {
	var errOutput error

	_, err := utils.JSONLoad(filePath, &config)
	if err != nil {
		return err
	}

	// Load provider definitions
	config.Providers = make(map[string]*ProviderConfig)

	walkFunc := func(filePath string, fileInfo os.FileInfo, err error) error {
		if fileInfo.IsDir() || !strings.HasSuffix(filePath, ".json") {
			return nil
		}

		_, providerName := path.Split(strings.TrimSuffix(filePath, ".json"))

		config.Lock()
		defer config.Unlock()

		config.Providers[providerName] = &ProviderConfig{}

		if fileInfo, err = utils.JSONLoad(filePath, config.Providers[providerName]); err != nil {
			err = fmt.Errorf("in %s, %s", filePath, err)
			if errOutput == nil {
				errOutput = err
			}

			return err
		}

		return nil
	}

	if err := utils.WalkDir(config.ProvidersDir, walkFunc); err != nil {
		return fmt.Errorf("unable to load provider definitions: %s", err)
	}

	if errOutput != nil {
		return errOutput
	}

	return nil
}
Exemplo n.º 2
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
}
Exemplo n.º 3
0
// Refresh triggers a full connector data update.
func (connector *RRDConnector) Refresh(originName string, outputChan chan *catalog.CatalogRecord) error {
	// Compile pattern
	re := regexp.MustCompile(connector.pattern)

	// Validate pattern keywords
	groups := make(map[string]bool)

	for _, key := range re.SubexpNames() {
		if key == "" {
			continue
		} else if key == "source" || key == "metric" {
			groups[key] = true
		} else {
			return fmt.Errorf("invalid pattern keyword `%s'", key)
		}
	}

	if !groups["source"] {
		return fmt.Errorf("missing pattern keyword `source'")
	} else if !groups["metric"] {
		return fmt.Errorf("missing pattern keyword `metric'")
	}

	// 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

		// Stop if previous error
		if err != nil {
			return err
		}

		// Skip non-files
		mode := fileInfo.Mode() & os.ModeType
		if mode != 0 {
			return nil
		}

		submatch := re.FindStringSubmatch(filePath[len(connector.path)+1:])
		if len(submatch) == 0 {
			logger.Log(logger.LevelInfo, "connector: rrd", "file `%s' does not match pattern, ignoring", filePath)
			return nil
		}

		if re.SubexpNames()[1] == "source" {
			sourceName = submatch[1]
			metricName = submatch[2]
		} else {
			sourceName = submatch[2]
			metricName = submatch[1]
		}

		if _, ok := connector.metrics[sourceName]; !ok {
			connector.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", err)
			return nil
		}

		if _, ok := info["ds.index"]; ok {
			for dsName := range info["ds.index"].(map[string]interface{}) {
				metricFullName := metricName + "/" + dsName

				connector.metrics[sourceName][metricFullName] = &rrdMetric{Dataset: dsName, FilePath: filePath}

				outputChan <- &catalog.CatalogRecord{
					Origin:    originName,
					Source:    sourceName,
					Metric:    metricFullName,
					Connector: connector,
				}
			}
		}

		return nil
	}

	if err := utils.WalkDir(connector.path, walkFunc); err != nil {
		return err
	}

	return nil
}
Exemplo n.º 4
0
// Refresh updates the current library by browsing the filesystem for stored data.
func (library *Library) Refresh() error {
	var itemType int

	// Empty library maps
	library.Groups = make(map[string]*Group)
	library.Scales = make(map[string]*Scale)
	library.Graphs = make(map[string]*Graph)
	library.Collections = make(map[string]*Collection)

	walkFunc := func(filePath string, fileInfo os.FileInfo, fileError error) error {
		mode := fileInfo.Mode() & os.ModeType
		if mode != 0 || !strings.HasSuffix(filePath, ".json") {
			return nil
		}

		_, itemID := path.Split(filePath[:len(filePath)-5])

		logger.Log(logger.LevelDebug, "library", "loading item `%s' from file `%s'", itemID, filePath)

		return library.LoadItem(itemID, itemType)
	}

	logger.Log(logger.LevelInfo, "library", "refresh started")

	for _, itemType = range []int{
		LibraryItemSourceGroup,
		LibraryItemMetricGroup,
		LibraryItemScale,
		LibraryItemGraph,
		LibraryItemCollection,
	} {
		dirPath := library.getDirPath(itemType)

		if _, err := os.Stat(dirPath); os.IsNotExist(err) {
			continue
		}

		if err := utils.WalkDir(dirPath, walkFunc); err != nil {
			logger.Log(logger.LevelError, "library", "%s", err)
		}
	}

	// Update collection items parent-children relations
	for _, collection := range library.Collections {
		if collection.ParentID == "" {
			continue
		}

		if _, ok := library.Collections[collection.ParentID]; !ok {
			logger.Log(logger.LevelError, "library", "unknown parent identifier `%s'", collection.ParentID)
			continue
		}

		collection.Parent = library.Collections[collection.ParentID]
		collection.Parent.Children = append(collection.Parent.Children, collection)
	}

	logger.Log(logger.LevelInfo, "library", "refresh completed")

	return nil
}