Use correct SemVer range condition. Fixes #38 (#39)

This commit is contained in:
Dominik Schulz 2016-11-28 15:49:25 +01:00 committed by Will Rouesnel
parent 37e6dd3bec
commit 8f3088611b

View File

@ -2,25 +2,24 @@ package main
import ( import (
"database/sql" "database/sql"
"errors"
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math" "math"
"net/http" "net/http"
"os" "os"
"strconv"
"time"
"regexp" "regexp"
"errors" "strconv"
"sync" "sync"
"time"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"github.com/blang/semver"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/log" "github.com/prometheus/common/log"
"github.com/blang/semver"
) )
var Version string = "0.0.1" var Version string = "0.0.1"
@ -116,10 +115,10 @@ func parseVersion(versionString string) (semver.Version, error) {
// User-friendly representation of a prometheus descriptor map // User-friendly representation of a prometheus descriptor map
type ColumnMapping struct { type ColumnMapping struct {
usage ColumnUsage `yaml:"usage"` usage ColumnUsage `yaml:"usage"`
description string `yaml:"description"` description string `yaml:"description"`
mapping map[string]float64 `yaml:"metric_mapping"` // Optional column mapping for MAPPEDMETRIC 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). supportedVersions semver.Range `yaml:"pg_version"` // Semantic version ranges which are supported. Unsupported columns are not queried (internally converted to DISCARD).
} }
func (this *ColumnMapping) UnmarshalYAML(unmarshal func(interface{}) error) error { func (this *ColumnMapping) UnmarshalYAML(unmarshal func(interface{}) error) error {
@ -232,7 +231,7 @@ var metricMaps = map[string]map[string]ColumnMapping{
"count": {GAUGE, "Number of locks", nil, nil}, "count": {GAUGE, "Number of locks", nil, nil},
}, },
"pg_stat_replication": map[string]ColumnMapping{ "pg_stat_replication": map[string]ColumnMapping{
"procpid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange("<9.2.0")}, "procpid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange("<9.2.0")},
"pid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange(">=9.2.0")}, "pid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange(">=9.2.0")},
"usesysid": {DISCARD, "OID of the user logged into this WAL sender process", nil, nil}, "usesysid": {DISCARD, "OID of the user logged into this WAL sender process", nil, nil},
"usename": {DISCARD, "Name of the user logged into this WAL sender process", nil, nil}, "usename": {DISCARD, "Name of the user logged into this WAL sender process", nil, nil},
@ -276,7 +275,7 @@ var metricMaps = map[string]map[string]ColumnMapping{
// the semver matching we do for columns. // the semver matching we do for columns.
type OverrideQuery struct { type OverrideQuery struct {
versionRange semver.Range versionRange semver.Range
query string query string
} }
// Overriding queries for namespaces above. // Overriding queries for namespaces above.
@ -358,7 +357,6 @@ var queryOverrides = map[string][]OverrideQuery{
}, },
// No query is applicable for 9.1 that gives any sensible data. // No query is applicable for 9.1 that gives any sensible data.
}, },
} }
// Convert the query override file to the version-specific query override file // Convert the query override file to the version-specific query override file
@ -509,7 +507,7 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu
// Check column version compatibility for the current map // Check column version compatibility for the current map
// Force to discard if not compatible. // Force to discard if not compatible.
if columnMapping.supportedVersions != nil { if columnMapping.supportedVersions != nil {
if columnMapping.supportedVersions(pgVersion) { if !columnMapping.supportedVersions(pgVersion) {
thisMap[columnName] = MetricMap{ thisMap[columnName] = MetricMap{
discard: true, discard: true,
conversion: func(in interface{}) (float64, bool) { conversion: func(in interface{}) (float64, bool) {
@ -683,26 +681,26 @@ func dbToString(t interface{}) (string, bool) {
// Exporter collects Postgres metrics. It implements prometheus.Collector. // Exporter collects Postgres metrics. It implements prometheus.Collector.
type Exporter struct { type Exporter struct {
dsn string dsn string
userQueriesPath string userQueriesPath string
duration, error prometheus.Gauge duration, error prometheus.Gauge
totalScrapes prometheus.Counter totalScrapes prometheus.Counter
// Last version used to calculate metric map. If mismatch on scrape, // Last version used to calculate metric map. If mismatch on scrape,
// then maps are recalculated. // then maps are recalculated.
lastMapVersion semver.Version lastMapVersion semver.Version
// Currently active variable map // Currently active variable map
variableMap map[string]MetricMapNamespace variableMap map[string]MetricMapNamespace
// Currently active metric map // Currently active metric map
metricMap map[string]MetricMapNamespace metricMap map[string]MetricMapNamespace
// Currently active query overrides // Currently active query overrides
queryOverrides map[string]string queryOverrides map[string]string
mappingMtx sync.RWMutex mappingMtx sync.RWMutex
} }
// NewExporter returns a new PostgreSQL exporter for the provided DSN. // NewExporter returns a new PostgreSQL exporter for the provided DSN.
func NewExporter(dsn string, userQueriesPath string) *Exporter { func NewExporter(dsn string, userQueriesPath string) *Exporter {
return &Exporter{ return &Exporter{
dsn: dsn, dsn: dsn,
userQueriesPath: userQueriesPath, userQueriesPath: userQueriesPath,
duration: prometheus.NewGauge(prometheus.GaugeOpts{ duration: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespace, Namespace: namespace,
@ -722,8 +720,8 @@ func NewExporter(dsn string, userQueriesPath string) *Exporter {
Name: "last_scrape_error", 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).",
}), }),
variableMap: nil, variableMap: nil,
metricMap: nil, metricMap: nil,
queryOverrides: nil, queryOverrides: nil,
} }
} }
@ -948,7 +946,7 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err
e.lastMapVersion = semanticVersion e.lastMapVersion = semanticVersion
if e.userQueriesPath != "" { if e.userQueriesPath != "" {
if err := addQueries(e.userQueriesPath, semanticVersion, e.metricMap, e.queryOverrides) ; err != nil { if err := addQueries(e.userQueriesPath, semanticVersion, e.metricMap, e.queryOverrides); err != nil {
log.Errorln("Failed to reload user queries:", e.userQueriesPath, err) log.Errorln("Failed to reload user queries:", e.userQueriesPath, err)
} }
} }