From f00c4b7b87daad0196b4ea4ed28170e91d522717 Mon Sep 17 00:00:00 2001 From: Hang Sun Date: Tue, 27 Feb 2018 10:20:44 -0800 Subject: [PATCH] Added command-line flag to disable the default metrics --- .gitignore | 1 + README.md | 6 +++ cmd/postgres_exporter/postgres_exporter.go | 47 ++++++++++++------- .../postgres_exporter_integration_test.go | 8 ++-- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index caefb3156..8a0619070 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.test *-stamp /.idea +/.vscode *.iml /cover.out /cover.*.out diff --git a/README.md b/README.md index f5aead03c..47092e3ba 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,12 @@ rich self-documenting metrics for the exporter. The -extend.query-path command-line argument specifies a YAML file containing additional queries to run. Some examples are provided in [queries.yaml](queries.yaml). +### Working with non-officially-supported postgres versions + +If you want to use this exporter to monitor a postgres installation that is not officially supported (e.g. 8.2.15) or a variant of postgres (e.g. Greenplum). +You may try to disable all internal metrics using the -disable-default-metrics command-line argument, then supply your own set of metrics definitions in +an external config file. + ### Running as non-superuser To be able to collect metrics from pg_stat_activity and pg_stat_replication as non-superuser you have to create views as a superuser, and assign permissions separately to those. In PostgreSQL, views run with the permissions of the user that created them so they can act as security barriers. diff --git a/cmd/postgres_exporter/postgres_exporter.go b/cmd/postgres_exporter/postgres_exporter.go index dbe4e2184..df9708471 100644 --- a/cmd/postgres_exporter/postgres_exporter.go +++ b/cmd/postgres_exporter/postgres_exporter.go @@ -33,10 +33,11 @@ import ( var Version = "0.0.1" var ( - listenAddress = kingpin.Flag("web.listen-address", "Address to listen on for web interface and telemetry.").Default(":9187").OverrideDefaultFromEnvar("PG_EXPORTER_WEB_LISTEN_ADDRESS").String() - metricPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").OverrideDefaultFromEnvar("PG_EXPORTER_WEB_TELEMETRY_PATH").String() - queriesPath = kingpin.Flag("extend.query-path", "Path to custom queries to run.").Default("").OverrideDefaultFromEnvar("PG_EXPORTER_EXTEND_QUERY_PATH").String() - onlyDumpMaps = kingpin.Flag("dumpmaps", "Do not run, simply dump the maps.").Bool() + listenAddress = kingpin.Flag("web.listen-address", "Address to listen on for web interface and telemetry.").Default(":9187").OverrideDefaultFromEnvar("PG_EXPORTER_WEB_LISTEN_ADDRESS").String() + metricPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").OverrideDefaultFromEnvar("PG_EXPORTER_WEB_TELEMETRY_PATH").String() + disableDefaultMetrics = kingpin.Flag("disable-default-metrics", "Do not include default metrics.").Default("false").OverrideDefaultFromEnvar("PG_EXPORTER_DISABLE_DEFAULT_METRICS").Bool() + queriesPath = kingpin.Flag("extend.query-path", "Path to custom queries to run.").Default("").OverrideDefaultFromEnvar("PG_EXPORTER_EXTEND_QUERY_PATH").String() + onlyDumpMaps = kingpin.Flag("dumpmaps", "Do not run, simply dump the maps.").Bool() ) // Metric name parts. @@ -668,13 +669,14 @@ type Exporter struct { // only, since it just points to the global. builtinMetricMaps map[string]map[string]ColumnMapping - dsn string - userQueriesPath string - duration prometheus.Gauge - error prometheus.Gauge - psqlUp prometheus.Gauge - userQueriesError *prometheus.GaugeVec - totalScrapes prometheus.Counter + dsn string + disableDefaultMetrics bool + userQueriesPath string + duration prometheus.Gauge + error prometheus.Gauge + psqlUp prometheus.Gauge + userQueriesError *prometheus.GaugeVec + totalScrapes prometheus.Counter // dbDsn is the connection string used to establish the dbConnection dbDsn string @@ -692,11 +694,12 @@ type Exporter struct { } // NewExporter returns a new PostgreSQL exporter for the provided DSN. -func NewExporter(dsn string, userQueriesPath string) *Exporter { +func NewExporter(dsn string, disableDefaultMetrics bool, userQueriesPath string) *Exporter { return &Exporter{ builtinMetricMaps: builtinMetricMaps, dsn: dsn, - userQueriesPath: userQueriesPath, + disableDefaultMetrics: disableDefaultMetrics, + userQueriesPath: userQueriesPath, duration: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Subsystem: exporter, @@ -913,7 +916,7 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err if err != nil { return fmt.Errorf("Error parsing version string: %v", err) } - if semanticVersion.LT(lowestSupportedVersion) { + if !e.disableDefaultMetrics && semanticVersion.LT(lowestSupportedVersion) { log.Warnln("PostgreSQL version is lower then our lowest supported version! Got", semanticVersion.String(), "minimum supported is", lowestSupportedVersion.String()) } @@ -922,8 +925,18 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err log.Infoln("Semantic Version Changed:", e.lastMapVersion.String(), "->", semanticVersion.String()) e.mappingMtx.Lock() - e.metricMap = makeDescMap(semanticVersion, e.builtinMetricMaps) - e.queryOverrides = makeQueryOverrideMap(semanticVersion, queryOverrides) + if e.disableDefaultMetrics { + e.metricMap = make(map[string]MetricMapNamespace) + } else { + e.metricMap = makeDescMap(semanticVersion, e.builtinMetricMaps) + } + + if e.disableDefaultMetrics { + e.queryOverrides = make(map[string]string) + } else { + e.queryOverrides = makeQueryOverrideMap(semanticVersion, queryOverrides) + } + e.lastMapVersion = semanticVersion if e.userQueriesPath != "" { @@ -1106,7 +1119,7 @@ func main() { log.Fatal("couldn't find environment variables describing the datasource to use") } - exporter := NewExporter(dsn, *queriesPath) + exporter := NewExporter(dsn, *disableDefaultMetrics, *queriesPath) defer func() { if exporter.dbConnection != nil { exporter.dbConnection.Close() // nolint: errcheck diff --git a/cmd/postgres_exporter/postgres_exporter_integration_test.go b/cmd/postgres_exporter/postgres_exporter_integration_test.go index 3387f2b56..fe35693a7 100644 --- a/cmd/postgres_exporter/postgres_exporter_integration_test.go +++ b/cmd/postgres_exporter/postgres_exporter_integration_test.go @@ -31,7 +31,7 @@ func (s *IntegrationSuite) SetUpSuite(c *C) { dsn := os.Getenv("DATA_SOURCE_NAME") c.Assert(dsn, Not(Equals), "") - exporter := NewExporter(dsn, "") + exporter := NewExporter(dsn, false, "") c.Assert(exporter, NotNil) // Assign the exporter to the suite s.e = exporter @@ -86,12 +86,12 @@ func (s *IntegrationSuite) TestInvalidDsnDoesntCrash(c *C) { }() // Send a bad DSN - exporter := NewExporter("invalid dsn", *queriesPath) + exporter := NewExporter("invalid dsn", false, *queriesPath) c.Assert(exporter, NotNil) exporter.scrape(ch) // Send a DSN to a non-listening port. - exporter = NewExporter("postgresql://nothing:nothing@127.0.0.1:1/nothing", *queriesPath) + exporter = NewExporter("postgresql://nothing:nothing@127.0.0.1:1/nothing", false, *queriesPath) c.Assert(exporter, NotNil) exporter.scrape(ch) } @@ -109,7 +109,7 @@ func (s *IntegrationSuite) TestUnknownMetricParsingDoesntCrash(c *C) { dsn := os.Getenv("DATA_SOURCE_NAME") c.Assert(dsn, Not(Equals), "") - exporter := NewExporter(dsn, "") + exporter := NewExporter(dsn, false, "") c.Assert(exporter, NotNil) // Convert the default maps into a list of empty maps.