Support connstring syntax when discovering databases ()

* Support connstring syntax when discovering databases

Support connstring DSNs (`host=... user=... password=... dbname=...`) in
addition to URIs (`postgresql://user:pass@host/dbname`) for purposes of
database discovery.

Connstring syntax is needed to support accessing PostgreSQL via Unix
domain sockets (`host=/run/postgres`), which is not really possible with
URI syntax.

* Appease gometalinter, don't shadow namespace
This commit is contained in:
Ivan Shapovalov 2021-01-31 14:21:38 +03:00 committed by GitHub
parent aea6fae7d6
commit 1ba1100a72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -601,6 +601,8 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
for namespace, intermediateMappings := range metricMaps {
thisMap := make(map[string]MetricMap)
namespace = strings.Replace(namespace, "pg", *metricPrefix, 1)
// Get the constant labels
var variableLabels []string
for columnName, columnMapping := range intermediateMappings.columnMappings {
@ -627,8 +629,6 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
}
}
namespace := strings.Replace(namespace, "pg", *metricPrefix, 1)
// Determine how to convert the column based on its usage.
// nolint: dupl
switch columnMapping.usage {
@ -1616,11 +1616,27 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
}
func (e *Exporter) discoverDatabaseDSNs() []string {
// connstring syntax is complex (and not sure if even regular).
// we don't need to parse it, so just superficially validate that it starts
// with a valid-ish keyword pair
connstringRe := regexp.MustCompile(`^ *[a-zA-Z0-9]+ *= *[^= ]+`)
dsns := make(map[string]struct{})
for _, dsn := range e.dsn {
parsedDSN, err := url.Parse(dsn)
if err != nil {
log.Errorf("Unable to parse DSN (%s): %v", loggableDSN(dsn), err)
var dsnURI *url.URL
var dsnConnstring string
if strings.HasPrefix(dsn, "postgresql://") {
var err error
dsnURI, err = url.Parse(dsn)
if err != nil {
log.Errorf("Unable to parse DSN as URI (%s): %v", loggableDSN(dsn), err)
continue
}
} else if connstringRe.MatchString(dsn) {
dsnConnstring = dsn
} else {
log.Errorf("Unable to parse DSN as either URI or connstring (%s)", loggableDSN(dsn))
continue
}
@ -1643,8 +1659,16 @@ func (e *Exporter) discoverDatabaseDSNs() []string {
if contains(e.excludeDatabases, databaseName) {
continue
}
parsedDSN.Path = databaseName
dsns[parsedDSN.String()] = struct{}{}
if dsnURI != nil {
dsnURI.Path = databaseName
dsn = dsnURI.String()
} else {
// replacing one dbname with another is complicated.
// just append new dbname to override.
dsn = fmt.Sprintf("%s dbname=%s", dsnConnstring, databaseName)
}
dsns[dsn] = struct{}{}
}
}