Skip to content

Commit 14780fe

Browse files
authored
Merge branch 'master' into master
2 parents 20ac124 + 3ead0f9 commit 14780fe

File tree

4 files changed

+113
-25
lines changed

4 files changed

+113
-25
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ FROM scratch
22

33
COPY postgres_exporter /postgres_exporter
44

5-
EXPOSE 9113
5+
EXPOSE 9187
66

77
ENTRYPOINT [ "/postgres_exporter" ]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ vet:
2121
go vet .
2222

2323
test:
24-
go test -v .
24+
go test -v -cover .
2525

2626
test-integration: postgres_exporter postgres_exporter_integration_test
2727
tests/test-smoke ./postgres_exporter ./postgres_exporter_integration_test

postgres_exporter.go

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,24 @@ package main
22

33
import (
44
"database/sql"
5+
"errors"
56
"flag"
67
"fmt"
78
"io/ioutil"
89
"math"
910
"net/http"
1011
"os"
11-
"strconv"
12-
"time"
1312
"regexp"
14-
"errors"
13+
"strconv"
1514
"sync"
15+
"time"
1616

1717
"gopkg.in/yaml.v2"
1818

19+
"github.com/blang/semver"
1920
_ "github.com/lib/pq"
2021
"github.com/prometheus/client_golang/prometheus"
2122
"github.com/prometheus/common/log"
22-
"github.com/blang/semver"
23-
2423
)
2524

2625
var Version string = "0.0.1"
@@ -116,10 +115,10 @@ func parseVersion(versionString string) (semver.Version, error) {
116115

117116
// User-friendly representation of a prometheus descriptor map
118117
type ColumnMapping struct {
119-
usage ColumnUsage `yaml:"usage"`
120-
description string `yaml:"description"`
121-
mapping map[string]float64 `yaml:"metric_mapping"` // Optional column mapping for MAPPEDMETRIC
122-
supportedVersions semver.Range `yaml:"pg_version"` // Semantic version ranges which are supported. Unsupported columns are not queried (internally converted to DISCARD).
118+
usage ColumnUsage `yaml:"usage"`
119+
description string `yaml:"description"`
120+
mapping map[string]float64 `yaml:"metric_mapping"` // Optional column mapping for MAPPEDMETRIC
121+
supportedVersions semver.Range `yaml:"pg_version"` // Semantic version ranges which are supported. Unsupported columns are not queried (internally converted to DISCARD).
123122
}
124123

125124
func (this *ColumnMapping) UnmarshalYAML(unmarshal func(interface{}) error) error {
@@ -232,7 +231,7 @@ var metricMaps = map[string]map[string]ColumnMapping{
232231
"count": {GAUGE, "Number of locks", nil, nil},
233232
},
234233
"pg_stat_replication": map[string]ColumnMapping{
235-
"procpid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange("<9.2.0")},
234+
"procpid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange("<9.2.0")},
236235
"pid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange(">=9.2.0")},
237236
"usesysid": {DISCARD, "OID of the user logged into this WAL sender process", nil, nil},
238237
"usename": {DISCARD, "Name of the user logged into this WAL sender process", nil, nil},
@@ -277,7 +276,7 @@ var metricMaps = map[string]map[string]ColumnMapping{
277276
// the semver matching we do for columns.
278277
type OverrideQuery struct {
279278
versionRange semver.Range
280-
query string
279+
query string
281280
}
282281

283282
// Overriding queries for namespaces above.
@@ -359,7 +358,6 @@ var queryOverrides = map[string][]OverrideQuery{
359358
},
360359
// No query is applicable for 9.1 that gives any sensible data.
361360
},
362-
363361
}
364362

365363
// Convert the query override file to the version-specific query override file
@@ -510,7 +508,10 @@ func makeDescMap(pgVersion semver.Version, metricMaps map[string]map[string]Colu
510508
// Check column version compatibility for the current map
511509
// Force to discard if not compatible.
512510
if columnMapping.supportedVersions != nil {
513-
if columnMapping.supportedVersions(pgVersion) {
511+
if !columnMapping.supportedVersions(pgVersion) {
512+
// It's very useful to be able to see what columns are being
513+
// rejected.
514+
log.Debugln(columnName, "is being forced to discard due to version incompatibility.")
514515
thisMap[columnName] = MetricMap{
515516
discard: true,
516517
conversion: func(in interface{}) (float64, bool) {
@@ -684,26 +685,26 @@ func dbToString(t interface{}) (string, bool) {
684685
// Exporter collects Postgres metrics. It implements prometheus.Collector.
685686
type Exporter struct {
686687
dsn string
687-
userQueriesPath string
688+
userQueriesPath string
688689
duration, error prometheus.Gauge
689690
totalScrapes prometheus.Counter
690691

691692
// Last version used to calculate metric map. If mismatch on scrape,
692693
// then maps are recalculated.
693-
lastMapVersion semver.Version
694+
lastMapVersion semver.Version
694695
// Currently active variable map
695-
variableMap map[string]MetricMapNamespace
696+
variableMap map[string]MetricMapNamespace
696697
// Currently active metric map
697-
metricMap map[string]MetricMapNamespace
698+
metricMap map[string]MetricMapNamespace
698699
// Currently active query overrides
699-
queryOverrides map[string]string
700-
mappingMtx sync.RWMutex
700+
queryOverrides map[string]string
701+
mappingMtx sync.RWMutex
701702
}
702703

703704
// NewExporter returns a new PostgreSQL exporter for the provided DSN.
704705
func NewExporter(dsn string, userQueriesPath string) *Exporter {
705706
return &Exporter{
706-
dsn: dsn,
707+
dsn: dsn,
707708
userQueriesPath: userQueriesPath,
708709
duration: prometheus.NewGauge(prometheus.GaugeOpts{
709710
Namespace: namespace,
@@ -723,8 +724,8 @@ func NewExporter(dsn string, userQueriesPath string) *Exporter {
723724
Name: "last_scrape_error",
724725
Help: "Whether the last scrape of metrics from PostgreSQL resulted in an error (1 for error, 0 for success).",
725726
}),
726-
variableMap: nil,
727-
metricMap: nil,
727+
variableMap: nil,
728+
metricMap: nil,
728729
queryOverrides: nil,
729730
}
730731
}
@@ -949,7 +950,7 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err
949950
e.lastMapVersion = semanticVersion
950951

951952
if e.userQueriesPath != "" {
952-
if err := addQueries(e.userQueriesPath, semanticVersion, e.metricMap, e.queryOverrides) ; err != nil {
953+
if err := addQueries(e.userQueriesPath, semanticVersion, e.metricMap, e.queryOverrides); err != nil {
953954
log.Errorln("Failed to reload user queries:", e.userQueriesPath, err)
954955
}
955956
}

postgres_exporter_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// +build !integration
2+
3+
package main
4+
5+
import (
6+
"testing"
7+
. "gopkg.in/check.v1"
8+
9+
"github.com/blang/semver"
10+
)
11+
12+
// Hook up gocheck into the "go test" runner.
13+
func Test(t *testing.T) { TestingT(t) }
14+
15+
type FunctionalSuite struct{
16+
e *Exporter
17+
}
18+
19+
var _ = Suite(&FunctionalSuite{})
20+
21+
func (s *FunctionalSuite) SetUpSuite(c *C) {
22+
23+
}
24+
25+
func (s *FunctionalSuite) TestSemanticVersionColumnDiscard(c *C) {
26+
testMetricMap := map[string]map[string]ColumnMapping{
27+
"test_namespace" : map[string]ColumnMapping{
28+
"metric_which_stays" : {COUNTER, "This metric should not be eliminated", nil, nil},
29+
"metric_which_discards" : {COUNTER, "This metric should be forced to DISCARD", nil, nil},
30+
},
31+
}
32+
33+
{
34+
// No metrics should be eliminated
35+
resultMap := makeDescMap(semver.MustParse("0.0.1"), testMetricMap)
36+
c.Check(
37+
resultMap["test_namespace"].columnMappings["metric_which_stays"].discard,
38+
Equals,
39+
false,
40+
)
41+
c.Check(
42+
resultMap["test_namespace"].columnMappings["metric_which_discards"].discard,
43+
Equals,
44+
false,
45+
)
46+
}
47+
48+
{
49+
// Update the map so the discard metric should be eliminated
50+
discardable_metric := testMetricMap["test_namespace"]["metric_which_discards"]
51+
discardable_metric.supportedVersions = semver.MustParseRange(">0.0.1")
52+
testMetricMap["test_namespace"]["metric_which_discards"] = discardable_metric
53+
54+
// Discard metric should be discarded
55+
resultMap := makeDescMap(semver.MustParse("0.0.1"), testMetricMap)
56+
c.Check(
57+
resultMap["test_namespace"].columnMappings["metric_which_stays"].discard,
58+
Equals,
59+
false,
60+
)
61+
c.Check(
62+
resultMap["test_namespace"].columnMappings["metric_which_discards"].discard,
63+
Equals,
64+
true,
65+
)
66+
}
67+
68+
{
69+
// Update the map so the discard metric should be kept but has a version
70+
discardable_metric := testMetricMap["test_namespace"]["metric_which_discards"]
71+
discardable_metric.supportedVersions = semver.MustParseRange(">0.0.1")
72+
testMetricMap["test_namespace"]["metric_which_discards"] = discardable_metric
73+
74+
// Discard metric should be discarded
75+
resultMap := makeDescMap(semver.MustParse("0.0.2"), testMetricMap)
76+
c.Check(
77+
resultMap["test_namespace"].columnMappings["metric_which_stays"].discard,
78+
Equals,
79+
false,
80+
)
81+
c.Check(
82+
resultMap["test_namespace"].columnMappings["metric_which_discards"].discard,
83+
Equals,
84+
false,
85+
)
86+
}
87+
}

0 commit comments

Comments
 (0)