github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/cmd/octsdb/config.go (about)

     1  // Copyright (c) 2016 Arista Networks, Inc.
     2  // Use of this source code is governed by the Apache License 2.0
     3  // that can be found in the COPYING file.
     4  
     5  package main
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"regexp"
    12  	"strings"
    13  )
    14  
    15  // Config is the representation of octsdb's JSON config file.
    16  type Config struct {
    17  	// Prefixes to subscribe to.
    18  	Subscriptions []string
    19  
    20  	// MetricPrefix, if set, is used to prefix all the metric names.
    21  	MetricPrefix string
    22  
    23  	// Metrics to collect and how to munge them.
    24  	Metrics map[string]*Metric
    25  }
    26  
    27  // A Metric to collect and how to massage it into an OpenTSDB put.
    28  type Metric struct {
    29  	// Path is a regexp to match on the Update's full path.
    30  	// The regexp must be a prefix match.
    31  	// The regexp can define named capture groups to use as tags.
    32  	Path string
    33  
    34  	// Path compiled as a regexp.
    35  	re *regexp.Regexp
    36  
    37  	// Additional tags to add to this metric.
    38  	Tags map[string]string
    39  
    40  	//Optional static value map
    41  	StaticValueMap map[string]int64
    42  }
    43  
    44  func loadConfig(path string) (*Config, error) {
    45  	cfg, err := ioutil.ReadFile(path)
    46  	if err != nil {
    47  		return nil, fmt.Errorf("Failed to load config: %v", err)
    48  	}
    49  	config := new(Config)
    50  	err = json.Unmarshal(cfg, config)
    51  	if err != nil {
    52  		return nil, fmt.Errorf("Failed to parse config: %v", err)
    53  	}
    54  	for _, metric := range config.Metrics {
    55  		metric.re = regexp.MustCompile(metric.Path)
    56  	}
    57  	return config, nil
    58  }
    59  
    60  // Match applies this config to the given OpenConfig path.
    61  // If the path doesn't match anything in the config, an empty string
    62  // is returned as the metric name.
    63  func (c *Config) Match(path string) (
    64  	metricName string,
    65  	tags map[string]string,
    66  	staticValueMap map[string]int64) {
    67  	tags = make(map[string]string)
    68  	staticValueMap = make(map[string]int64)
    69  
    70  	for name, metric := range c.Metrics {
    71  		found := metric.re.FindStringSubmatch(path)
    72  		if found == nil {
    73  			continue
    74  		}
    75  		metricName = name
    76  		for i, name := range metric.re.SubexpNames() {
    77  			if i == 0 {
    78  				continue
    79  			} else if name == "" {
    80  				if metricName != "" {
    81  					metricName += "/"
    82  				}
    83  				metricName += found[i]
    84  			} else {
    85  				tags[name] = found[i]
    86  			}
    87  		}
    88  		for tag, value := range metric.Tags {
    89  			tags[tag] = value
    90  		}
    91  
    92  		for initName, newName := range metric.StaticValueMap {
    93  			staticValueMap[initName] = newName
    94  		}
    95  		break
    96  	}
    97  	if metricName != "" {
    98  		metricName = strings.ToLower(strings.Replace(metricName, "/", ".", -1))
    99  		if c.MetricPrefix != "" {
   100  			metricName = c.MetricPrefix + "." + metricName
   101  		}
   102  	}
   103  	return
   104  }