Skip to content

Commit f554139

Browse files
committed
Add pg_static synthetic key to collect Postgres version.
Similar to the node_exporter, this key is synthetic and used to create a constant metric which records the version strings of PostgreSQL in its labels.
1 parent 8c0f2ed commit f554139

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

postgres_exporter.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
_ "github.com/lib/pq"
1717
"github.com/prometheus/client_golang/prometheus"
1818
"github.com/prometheus/common/log"
19+
"regexp"
1920
)
2021

2122
var Version string = "0.0.1"
@@ -45,8 +46,15 @@ const (
4546
namespace = "pg"
4647
// Subsystems.
4748
exporter = "exporter"
49+
// Metric label used for static string data thats handy to send to Prometheus
50+
// e.g. version
51+
staticLabelName = "static"
4852
)
4953

54+
// Highest version of Postgres we have explicit behavior for. This is the
55+
// assumed default if the version string does match any known versions.
56+
const HighestSupportedVersion = "9.6"
57+
5058
// landingPage contains the HTML served at '/'.
5159
// TODO: Make this nicer and more informative.
5260
var landingPage = []byte(`<html>
@@ -69,8 +77,25 @@ const (
6977
DURATION ColumnUsage = iota // This column should be interpreted as a text duration (and converted to milliseconds)
7078
)
7179

72-
// Which metric mapping should be acquired using "SHOW" queries
73-
const SHOW_METRIC = "pg_runtime_variables"
80+
// Special case matric mappings
81+
const (
82+
// Which metric mapping should be acquired using "SHOW" queries
83+
SHOW_METRIC = "pg_runtime_variables"
84+
)
85+
86+
// Regex used to get the "short-version" from the postgres version field.
87+
var versionRegex = regexp.MustCompile(`^\w+ (\d+\.\d+)`)
88+
89+
// Parses the version of postgres into the short version string we can use to
90+
// match behaviors.
91+
func parseVersion(versionString string) string {
92+
submatches := versionRegex.FindStringSubmatch(versionString)
93+
if len(submatches) > 1 {
94+
return submatches[1]
95+
}
96+
log.Debugln("Could not parse postgres version regex:", versionString)
97+
return ""
98+
}
7499

75100
// User-friendly representation of a prometheus descriptor map
76101
type ColumnMapping struct {
@@ -580,6 +605,20 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
580605
}
581606
defer db.Close()
582607

608+
log.Debugln("Querying Postgres Version")
609+
versionRow := db.QueryRow("SELECT version();")
610+
var versionString string
611+
err = versionRow.Scan(&versionString)
612+
if err != nil {
613+
log.Errorln("Error scanning version string:", err)
614+
e.error.Set(1)
615+
return
616+
}
617+
shortVersion := parseVersion(versionString)
618+
// Output the version as a special metric
619+
versionDesc := prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, staticLabelName), "Version string as reported by postgres", []string{"version", "short_version"}, nil)
620+
ch <- prometheus.MustNewConstMetric(versionDesc, prometheus.UntypedValue, 1, versionString, shortVersion)
621+
583622
log.Debugln("Querying SHOW variables")
584623
for _, mapping := range e.variableMap {
585624
for columnName, columnMapping := range mapping.columnMappings {

0 commit comments

Comments
 (0)