diff --git a/collector/generic_collector.go b/collector/generic_collector.go index a7d5f7ce..27b04e32 100644 --- a/collector/generic_collector.go +++ b/collector/generic_collector.go @@ -16,7 +16,9 @@ package collector import ( "encoding/json" + "fmt" "io/ioutil" + "regexp" "time" "github.com/google/cadvisor/info/v2" @@ -28,6 +30,17 @@ type GenericCollector struct { //holds information extracted from the config file for a collector configFile Config + + //holds information necessary to extract metrics + info *collectorInfo +} + +type collectorInfo struct { + //minimum polling frequency among all metrics + minPollingFrequency time.Duration + + //regular expresssions for all metrics + regexps []*regexp.Regexp } //Returns a new collector using the information extracted from the configfile @@ -45,8 +58,30 @@ func NewCollector(collectorName string, configfile string) (*GenericCollector, e //TODO : Add checks for validity of config file (eg : Accurate JSON fields) + if len(configInJSON.MetricsConfig) == 0 { + return nil, fmt.Errorf("No metrics provided in config") + } + + minPollFrequency := configInJSON.MetricsConfig[0].PollingFrequency + regexprs := make([]*regexp.Regexp, len(configInJSON.MetricsConfig)) + + for ind, metricConfig := range configInJSON.MetricsConfig { + if metricConfig.PollingFrequency < minPollFrequency { + minPollFrequency = metricConfig.PollingFrequency + } + + regexprs[ind], err = regexp.Compile(metricConfig.Regex) + if err != nil { + return nil, fmt.Errorf("Invalid regexp %v for metric %v", metricConfig.Regex, metricConfig.Name) + } + } + return &GenericCollector{ - name: collectorName, configFile: configInJSON, + name: collectorName, + configFile: configInJSON, + info: &collectorInfo{ + minPollingFrequency: minPollFrequency, + regexps: regexprs}, }, nil } diff --git a/collector/generic_collector_test.go b/collector/generic_collector_test.go index c988a8c6..ca875d60 100644 --- a/collector/generic_collector_test.go +++ b/collector/generic_collector_test.go @@ -22,19 +22,39 @@ import ( "github.com/stretchr/testify/assert" ) +func TestEmptyConfig(t *testing.T) { + assert := assert.New(t) + + emptyConfig := ` + { + "endpoint" : "http://localhost:8000/nginx_status", + "metrics_config" : [ + ] + } + ` + + //Create a temporary config file 'temp.json' with invalid json format + assert.NoError(ioutil.WriteFile("temp.json", []byte(emptyConfig), 0777)) + + _, err := NewCollector("tempCollector", "temp.json") + assert.Error(err) + + assert.NoError(os.Remove("temp.json")) +} + func TestConfigWithErrors(t *testing.T) { assert := assert.New(t) - //Syntax error: Missed '"' after active connections + //Syntax error: Missed '"' after activeConnections invalid := ` { - "endpoint" : "host:port/nginx_status", - "metricsConfig" : [ + "endpoint" : "http://localhost:8000/nginx_status", + "metrics_config" : [ { "name" : "activeConnections, - "metricType" : "gauge", + "metric_type" : "gauge", "units" : "integer", - "pollingFrequency" : "10s", + "polling_frequency" : 10, "regex" : "Active connections: ([0-9]+)" } ] @@ -50,6 +70,41 @@ func TestConfigWithErrors(t *testing.T) { assert.NoError(os.Remove("temp.json")) } +func TestConfigWithRegexErrors(t *testing.T) { + assert := assert.New(t) + + //Error: Missed operand for '+' in activeConnections regex + invalid := ` + { + "endpoint" : "host:port/nginx_status", + "metrics_config" : [ + { + "name" : "activeConnections", + "metric_type" : "gauge", + "units" : "integer", + "polling_frequency" : 10, + "regex" : "Active connections: (+)" + }, + { + "name" : "reading", + "metric_type" : "gauge", + "units" : "integer", + "polling_frequency" : 10, + "regex" : "Reading: ([0-9]+) .*" + } + ] + } + ` + + //Create a temporary config file 'temp.json' + assert.NoError(ioutil.WriteFile("temp.json", []byte(invalid), 0777)) + + _, err := NewCollector("tempCollector", "temp.json") + assert.Error(err) + + assert.NoError(os.Remove("temp.json")) +} + func TestConfig(t *testing.T) { assert := assert.New(t)