Skip to content

Commit 1ba1100

Browse files
authored
Support connstring syntax when discovering databases (prometheus-community#473)
* 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
1 parent aea6fae commit 1ba1100

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

cmd/postgres_exporter/postgres_exporter.go

+31-7
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
601601
for namespace, intermediateMappings := range metricMaps {
602602
thisMap := make(map[string]MetricMap)
603603

604+
namespace = strings.Replace(namespace, "pg", *metricPrefix, 1)
605+
604606
// Get the constant labels
605607
var variableLabels []string
606608
for columnName, columnMapping := range intermediateMappings.columnMappings {
@@ -627,8 +629,6 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
627629
}
628630
}
629631

630-
namespace := strings.Replace(namespace, "pg", *metricPrefix, 1)
631-
632632
// Determine how to convert the column based on its usage.
633633
// nolint: dupl
634634
switch columnMapping.usage {
@@ -1616,11 +1616,27 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
16161616
}
16171617

16181618
func (e *Exporter) discoverDatabaseDSNs() []string {
1619+
// connstring syntax is complex (and not sure if even regular).
1620+
// we don't need to parse it, so just superficially validate that it starts
1621+
// with a valid-ish keyword pair
1622+
connstringRe := regexp.MustCompile(`^ *[a-zA-Z0-9]+ *= *[^= ]+`)
1623+
16191624
dsns := make(map[string]struct{})
16201625
for _, dsn := range e.dsn {
1621-
parsedDSN, err := url.Parse(dsn)
1622-
if err != nil {
1623-
log.Errorf("Unable to parse DSN (%s): %v", loggableDSN(dsn), err)
1626+
var dsnURI *url.URL
1627+
var dsnConnstring string
1628+
1629+
if strings.HasPrefix(dsn, "postgresql://") {
1630+
var err error
1631+
dsnURI, err = url.Parse(dsn)
1632+
if err != nil {
1633+
log.Errorf("Unable to parse DSN as URI (%s): %v", loggableDSN(dsn), err)
1634+
continue
1635+
}
1636+
} else if connstringRe.MatchString(dsn) {
1637+
dsnConnstring = dsn
1638+
} else {
1639+
log.Errorf("Unable to parse DSN as either URI or connstring (%s)", loggableDSN(dsn))
16241640
continue
16251641
}
16261642

@@ -1643,8 +1659,16 @@ func (e *Exporter) discoverDatabaseDSNs() []string {
16431659
if contains(e.excludeDatabases, databaseName) {
16441660
continue
16451661
}
1646-
parsedDSN.Path = databaseName
1647-
dsns[parsedDSN.String()] = struct{}{}
1662+
1663+
if dsnURI != nil {
1664+
dsnURI.Path = databaseName
1665+
dsn = dsnURI.String()
1666+
} else {
1667+
// replacing one dbname with another is complicated.
1668+
// just append new dbname to override.
1669+
dsn = fmt.Sprintf("%s dbname=%s", dsnConnstring, databaseName)
1670+
}
1671+
dsns[dsn] = struct{}{}
16481672
}
16491673
}
16501674

0 commit comments

Comments
 (0)