From a185383f1b694af8322a968137a90cd98611be68 Mon Sep 17 00:00:00 2001 From: Will Rouesnel Date: Tue, 6 Mar 2018 23:04:49 +1100 Subject: [PATCH] Fix linter issues. --- collector/pg_setting.go | 4 +- collector/pg_setting_test.go | 1 + collector/postgres_exporter.go | 64 ++++++++++++++++------------- collector/postgres_exporter_test.go | 4 +- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/collector/pg_setting.go b/collector/pg_setting.go index a20166b2..26a8861f 100644 --- a/collector/pg_setting.go +++ b/collector/pg_setting.go @@ -20,7 +20,7 @@ func querySettings(ch chan<- prometheus.Metric, db *sql.DB) error { // // NOTE: If you add more vartypes here, you must update the supported // types in normaliseUnit() below - query := "SELECT name, setting, COALESCE(unit, ''), short_desc, vartype FROM pg_settings WHERE vartype IN ('bool', 'integer', 'real');" + query := "SELECT name, setting, COALESCE(unit, ''), short_desc, vartype FROM pg_settings WHERE vartype IN ('bool', 'integer', 'real');" // nolint: lll rows, err := db.Query(query) if err != nil { @@ -82,6 +82,8 @@ func (s *pgSetting) metric() prometheus.Metric { return prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, val) } +// TODO: fix this lint problem +// nolint: nakedret func (s *pgSetting) normaliseUnit() (val float64, unit string, err error) { val, err = strconv.ParseFloat(s.setting, 64) if err != nil { diff --git a/collector/pg_setting_test.go b/collector/pg_setting_test.go index ede3765e..545e1bc8 100644 --- a/collector/pg_setting_test.go +++ b/collector/pg_setting_test.go @@ -11,6 +11,7 @@ type PgSettingSuite struct{} var _ = Suite(&PgSettingSuite{}) +// nolint: lll var fixtures = []fixture{ { p: pgSetting{ diff --git a/collector/postgres_exporter.go b/collector/postgres_exporter.go index bee9a8e8..b92fdccd 100644 --- a/collector/postgres_exporter.go +++ b/collector/postgres_exporter.go @@ -16,7 +16,7 @@ import ( "time" "github.com/blang/semver" - _ "github.com/lib/pq" + _ "github.com/lib/pq" // postgres library needs postgres driver "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/log" "gopkg.in/yaml.v2" @@ -44,7 +44,7 @@ const ( COUNTER ColumnUsage = iota // Use this column as a counter GAUGE ColumnUsage = iota // Use this column as a gauge MAPPEDMETRIC ColumnUsage = iota // Use this column with the supplied mapping of text values - DURATION ColumnUsage = iota // This column should be interpreted as a text duration (and converted to milliseconds) + DURATION ColumnUsage = iota // Column should be interpreted as a text duration (and converted to milliseconds) ) // UnmarshalYAML implements the yaml.Unmarshaller interface. @@ -80,10 +80,12 @@ func parseVersion(versionString string) (semver.Version, error) { // ColumnMapping is the user-friendly representation of a prometheus descriptor map type ColumnMapping struct { - usage ColumnUsage `yaml:"usage"` - description string `yaml:"description"` - mapping map[string]float64 `yaml:"metric_mapping"` // Optional column mapping for MAPPEDMETRIC - supportedVersions semver.Range `yaml:"pg_version"` // Semantic version ranges which are supported. Unsupported columns are not queried (internally converted to DISCARD). + usage ColumnUsage `yaml:"usage"` + description string `yaml:"description"` + mapping map[string]float64 `yaml:"metric_mapping"` // Optional column mapping for MAPPEDMETRIC + // Semantic version ranges which are supported. Unsupported columns are not queried + // (internally converted to DISCARD). + supportedVersions semver.Range `yaml:"pg_version"` } // UnmarshalYAML implements yaml.Unmarshaller @@ -107,7 +109,7 @@ type MetricMap struct { conversion func(interface{}) (float64, bool) // Conversion function to turn PG result into float64 } -// TODO: revisit this with the semver system +// DumpMaps simply exports the internal metric maps. func DumpMaps() { // TODO: make this function part of the exporter for name, cmap := range builtinMetricMaps { @@ -127,6 +129,7 @@ func DumpMaps() { } } +// nolint: lll var builtinMetricMaps = map[string]map[string]ColumnMapping{ "pg_stat_bgwriter": { "checkpoints_timed": {COUNTER, "Number of scheduled checkpoints that have been performed", nil, nil}, @@ -236,6 +239,7 @@ type OverrideQuery struct { // Overriding queries for namespaces above. // TODO: validate this is a closed set in tests, and there are no overlaps +// nolint: lll var queryOverrides = map[string][]OverrideQuery{ "pg_locks": { { @@ -357,7 +361,7 @@ func makeQueryOverrideMap(pgVersion semver.Version, queryOverrides map[string][] // TODO: test code for all cu. // TODO: use proper struct type system // TODO: the YAML this supports is "non-standard" - we should move away from it. -func addQueries(content []byte, pgVersion semver.Version, exporterMap map[string]MetricMapNamespace, queryOverrideMap map[string]string) error { +func addQueries(content []byte, pgVersion semver.Version, exporterMap map[string]MetricMapNamespace, queryOverrideMap map[string]string) error { //nolint: lll var extra map[string]interface{} err := yaml.Unmarshal(content, &extra) @@ -449,7 +453,7 @@ func addQueries(content []byte, pgVersion semver.Version, exporterMap map[string } // Turn the MetricMap column mapping into a prometheus descriptor mapping. -func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]ColumnMapping) map[string]MetricMapNamespace { +func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]ColumnMapping) map[string]MetricMapNamespace { //nolint: lll var metricMap = make(map[string]MetricMapNamespace) for namespace, mappings := range metricMaps { @@ -473,7 +477,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu log.Debugln(columnName, "is being forced to discard due to version incompatibility.") thisMap[columnName] = MetricMap{ discard: true, - conversion: func(in interface{}) (float64, bool) { + conversion: func(in interface{}) (float64, bool) { // nolint: unparam return math.NaN(), true }, } @@ -482,18 +486,19 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu } // Determine how to convert the column based on its usage. + // nolint: dupl switch columnMapping.usage { case DISCARD, LABEL: thisMap[columnName] = MetricMap{ discard: true, - conversion: func(in interface{}) (float64, bool) { + conversion: func(in interface{}) (float64, bool) { // nolint: unparam return math.NaN(), true }, } case COUNTER: thisMap[columnName] = MetricMap{ vtype: prometheus.CounterValue, - desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), + desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), //nolint: lll conversion: func(in interface{}) (float64, bool) { return dbToFloat64(in) }, @@ -501,7 +506,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu case GAUGE: thisMap[columnName] = MetricMap{ vtype: prometheus.GaugeValue, - desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), + desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), //nolint: lll conversion: func(in interface{}) (float64, bool) { return dbToFloat64(in) }, @@ -509,7 +514,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu case MAPPEDMETRIC: thisMap[columnName] = MetricMap{ vtype: prometheus.GaugeValue, - desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), + desc: prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, columnName), columnMapping.description, constLabels, nil), //nolint: lll conversion: func(in interface{}) (float64, bool) { text, ok := in.(string) if !ok { @@ -526,7 +531,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu case DURATION: thisMap[columnName] = MetricMap{ vtype: prometheus.GaugeValue, - desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_milliseconds", namespace, columnName), columnMapping.description, constLabels, nil), + desc: prometheus.NewDesc(fmt.Sprintf("%s_%s_milliseconds", namespace, columnName), columnMapping.description, constLabels, nil), //nolint: lll conversion: func(in interface{}) (float64, bool) { var durationString string switch t := in.(type) { @@ -561,6 +566,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu } // convert a string to the corresponding ColumnUsage +// nolint: nakedret func stringToColumnUsage(s string) (u ColumnUsage, err error) { switch s { case "DISCARD": @@ -693,24 +699,25 @@ func NewExporter(dsn string, userQueriesPath string) *Exporter { Namespace: namespace, Subsystem: exporter, Name: "last_scrape_error", - Help: "Whether the last scrape of metrics from PostgreSQL resulted in an error (1 for error, 0 for success).", + Help: "Whether the last scrape of metrics from PostgreSQL resulted in an error (1 for error, 0 for success).", //nolint: lll }), psqlUp: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "up", - Help: "Whether the last scrape of metrics from PostgreSQL was able to connect to the server (1 for yes, 0 for no).", + Help: "Whether the last scrape of metrics from PostgreSQL was able to connect to the server (1 for yes, 0 for no).", //nolint: lll }), userQueriesError: prometheus.NewGaugeVec(prometheus.GaugeOpts{ Namespace: namespace, Subsystem: exporter, Name: "user_queries_load_error", - Help: "Whether the user queries file was loaded and parsed successfully (1 for error, 0 for success).", + Help: "Whether the user queries file was loaded and parsed successfully (1 for error, 0 for success).", //nolint: lll }, []string{"filename", "hashsum"}), metricMap: nil, queryOverrides: nil, } } +// Close shutdowns any database connection, and should be called before releasing the collector. func (e *Exporter) Close() { if e.dbConnection != nil { e.dbConnection.Close() // nolint: errcheck @@ -765,7 +772,7 @@ func newDesc(subsystem, name, help string) *prometheus.Desc { // Query within a namespace mapping and emit metrics. Returns fatal errors if // the scrape fails, and a slice of errors if they were non-fatal. -func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace string, mapping MetricMapNamespace, queryOverrides map[string]string) ([]error, error) { +func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace string, mapping MetricMapNamespace, queryOverrides map[string]string) ([]error, error) { //nolint: lll // Check for a query override for this namespace query, found := queryOverrides[namespace] @@ -783,10 +790,9 @@ func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace st if !found { // I've no idea how to avoid this properly at the moment, but this is // an admin tool so you're not injecting SQL right? - // nolint: gas - rows, err = db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) + rows, err = db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gas, safesql } else { - rows, err = db.Query(query) + rows, err = db.Query(query) // nolint: gas, safesql } if err != nil { return []error{}, errors.New(fmt.Sprintln("Error running query on database: ", namespace, err)) @@ -837,7 +843,7 @@ func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace st value, ok := dbToFloat64(columnData[idx]) if !ok { - nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unexpected error parsing column: ", namespace, columnName, columnData[idx]))) + nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unexpected error parsing column: ", namespace, columnName, columnData[idx]))) // nolint: lll continue } @@ -846,13 +852,13 @@ func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace st } else { // Unknown metric. Report as untyped if scan to float64 works, else note an error too. metricLabel := fmt.Sprintf("%s_%s", namespace, columnName) - desc := prometheus.NewDesc(metricLabel, fmt.Sprintf("Unknown metric from %s", namespace), mapping.labels, nil) + desc := prometheus.NewDesc(metricLabel, fmt.Sprintf("Unknown metric from %s", namespace), mapping.labels, nil) // nolint: lll // Its not an error to fail here, since the values are // unexpected anyway. value, ok := dbToFloat64(columnData[idx]) if !ok { - nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unparseable column type - discarding: ", namespace, columnName, err))) + nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unparseable column type - discarding: ", namespace, columnName, err))) // nolint: lll continue } ch <- prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, value, labels...) @@ -864,14 +870,14 @@ func queryNamespaceMapping(ch chan<- prometheus.Metric, db *sql.DB, namespace st // Iterate through all the namespace mappings in the exporter and run their // queries. -func queryNamespaceMappings(ch chan<- prometheus.Metric, db *sql.DB, metricMap map[string]MetricMapNamespace, queryOverrides map[string]string) map[string]error { +func queryNamespaceMappings(ch chan<- prometheus.Metric, db *sql.DB, metricMap map[string]MetricMapNamespace, queryOverrides map[string]string) map[string]error { // nolint: lll // Return a map of namespace -> errors namespaceErrors := make(map[string]error) for namespace, mapping := range metricMap { log.Debugln("Querying namespace: ", namespace) nonFatalErrors, err := queryNamespaceMapping(ch, db, namespace, mapping, queryOverrides) - // Serious error - a namespace disappeard + // Serious error - a namespace disappeared if err != nil { namespaceErrors[namespace] = err log.Infoln(err) @@ -901,7 +907,7 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err return fmt.Errorf("Error parsing version string: %v", err) } if semanticVersion.LT(lowestSupportedVersion) { - log.Warnln("PostgreSQL version is lower then our lowest supported version! Got", semanticVersion.String(), "minimum supported is", lowestSupportedVersion.String()) + log.Warnln("PostgreSQL version is lower then our lowest supported version! Got", semanticVersion.String(), "minimum supported is", lowestSupportedVersion.String()) // nolint: lll } // Check if semantic version changed and recalculate maps if needed. @@ -1030,7 +1036,7 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) { } } -// try to get the DataSource +// GetDataSource tries to read postgres database connection data from the usual environment variables. // DATA_SOURCE_NAME always wins so we do not break older versions // reading secrets from files wins over secrets in environment variables // DATA_SOURCE_NAME > DATA_SOURCE_{USER|FILE}_FILE > DATA_SOURCE_{USER|FILE} diff --git a/collector/postgres_exporter_test.go b/collector/postgres_exporter_test.go index bc4e5494..56be2357 100644 --- a/collector/postgres_exporter_test.go +++ b/collector/postgres_exporter_test.go @@ -47,6 +47,7 @@ func (s *FunctionalSuite) TestSemanticVersionColumnDiscard(c *C) { ) } + // nolint: dupl { // Update the map so the discard metric should be eliminated discardableMetric := testMetricMap["test_namespace"]["metric_which_discards"] @@ -67,6 +68,7 @@ func (s *FunctionalSuite) TestSemanticVersionColumnDiscard(c *C) { ) } + // nolint: dupl { // Update the map so the discard metric should be kept but has a version discardableMetric := testMetricMap["test_namespace"]["metric_which_discards"] @@ -163,7 +165,7 @@ func (s *FunctionalSuite) TestPostgresVersionParsing(c *C) { expected: "9.5.4", }, { - input: "EnterpriseDB 9.6.5.10 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit", + input: "EnterpriseDB 9.6.5.10 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit", // nolint: lll expected: "9.6.5", }, }