Skip to content

Commit 6c13d3f

Browse files
committed
Add first set of tests + some helper functions cribbed from
mysqld_exporter Signed-off-by: Felix Yuan <[email protected]>
1 parent 24b8e39 commit 6c13d3f

File tree

5 files changed

+111
-4
lines changed

5 files changed

+111
-4
lines changed

collector/collector_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package collector
2+
3+
import (
4+
"strings"
5+
6+
"github.com/prometheus/client_golang/prometheus"
7+
dto "github.com/prometheus/client_model/go"
8+
)
9+
10+
type labelMap map[string]string
11+
12+
type MetricResult struct {
13+
labels labelMap
14+
value float64
15+
metricType dto.MetricType
16+
}
17+
18+
func readMetric(m prometheus.Metric) MetricResult {
19+
pb := &dto.Metric{}
20+
m.Write(pb)
21+
labels := make(labelMap, len(pb.Label))
22+
for _, v := range pb.Label {
23+
labels[v.GetName()] = v.GetValue()
24+
}
25+
if pb.Gauge != nil {
26+
return MetricResult{labels: labels, value: pb.GetGauge().GetValue(), metricType: dto.MetricType_GAUGE}
27+
}
28+
if pb.Counter != nil {
29+
return MetricResult{labels: labels, value: pb.GetCounter().GetValue(), metricType: dto.MetricType_COUNTER}
30+
}
31+
if pb.Untyped != nil {
32+
return MetricResult{labels: labels, value: pb.GetUntyped().GetValue(), metricType: dto.MetricType_UNTYPED}
33+
}
34+
panic("Unsupported metric type")
35+
}
36+
37+
func sanitizeQuery(q string) string {
38+
q = strings.Join(strings.Fields(q), " ")
39+
q = strings.Replace(q, "(", "\\(", -1)
40+
q = strings.Replace(q, ")", "\\)", -1)
41+
q = strings.Replace(q, "*", "\\*", -1)
42+
q = strings.Replace(q, "$", "\\$", -1)
43+
return q
44+
}

collector/pg_database.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ var pgDatabaseSizeBytes = prometheus.NewDesc(
4747
[]string{"datname"}, nil,
4848
)
4949

50+
var pgDatabaseQuery = "SELECT pg_database.datname FROM pg_database;"
51+
var pgDatabaseSizeQuery = "SELECT pg_database_size($1)"
52+
5053
// Update implements Collector and exposes database size.
5154
// It is called by the Prometheus registry when collecting metrics.
5255
// The list of databases is retrieved from pg_database and filtered
@@ -58,9 +61,7 @@ var pgDatabaseSizeBytes = prometheus.NewDesc(
5861
func (c PGDatabaseCollector) Update(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
5962
// Query the list of databases
6063
rows, err := db.QueryContext(ctx,
61-
`SELECT pg_database.datname
62-
FROM pg_database;
63-
`,
64+
pgDatabaseQuery,
6465
)
6566
if err != nil {
6667
return err
@@ -88,7 +89,7 @@ func (c PGDatabaseCollector) Update(ctx context.Context, db *sql.DB, ch chan<- p
8889
// Query the size of the databases
8990
for _, datname := range databases {
9091
var size int64
91-
err = db.QueryRowContext(ctx, "SELECT pg_database_size($1)", datname).Scan(&size)
92+
err = db.QueryRowContext(ctx, pgDatabaseSizeQuery, datname).Scan(&size)
9293
if err != nil {
9394
return err
9495
}

collector/pg_database_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package collector
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/DATA-DOG/go-sqlmock"
8+
"github.com/prometheus/client_golang/prometheus"
9+
dto "github.com/prometheus/client_model/go"
10+
"github.com/smartystreets/goconvey/convey"
11+
)
12+
13+
func TestPGDatabaseCollector(t *testing.T) {
14+
db, mock, err := sqlmock.New()
15+
if err != nil {
16+
t.Fatalf("Error opening a stub db connection: %s", err)
17+
}
18+
defer db.Close()
19+
20+
mock.ExpectQuery(sanitizeQuery(pgDatabaseQuery)).WillReturnRows(sqlmock.NewRows([]string{"datname"}).
21+
AddRow("postgres"))
22+
23+
mock.ExpectQuery(sanitizeQuery(pgDatabaseSizeQuery)).WithArgs("postgres").WillReturnRows(sqlmock.NewRows([]string{"pg_database_size"}).
24+
AddRow(1024))
25+
26+
ch := make(chan prometheus.Metric)
27+
go func() {
28+
defer close(ch)
29+
c := PGDatabaseCollector{}
30+
if err := c.Update(context.Background(), db, ch); err != nil {
31+
t.Errorf("Error calling PGDatabaseCollector.Update: %s", err)
32+
}
33+
}()
34+
35+
expected := []MetricResult{
36+
{labels: labelMap{"datname": "postgres"}, value: 1024, metricType: dto.MetricType_GAUGE},
37+
}
38+
convey.Convey("Metrics comparison", t, func() {
39+
for _, expect := range expected {
40+
m := readMetric(<-ch)
41+
convey.So(expect, convey.ShouldResemble, m)
42+
}
43+
})
44+
if err := mock.ExpectationsWereMet(); err != nil {
45+
t.Errorf("there were unfulfilled exceptions: %s", err)
46+
}
47+
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/prometheus-community/postgres_exporter
33
go 1.19
44

55
require (
6+
github.com/DATA-DOG/go-sqlmock v1.5.0
67
github.com/alecthomas/kingpin/v2 v2.3.2
78
github.com/blang/semver/v4 v4.0.0
89
github.com/go-kit/log v0.2.1
@@ -23,13 +24,17 @@ require (
2324
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
2425
github.com/go-logfmt/logfmt v0.5.1 // indirect
2526
github.com/golang/protobuf v1.5.2 // indirect
27+
github.com/gopherjs/gopherjs v1.17.2 // indirect
2628
github.com/jpillora/backoff v1.0.0 // indirect
29+
github.com/jtolds/gls v4.20.0+incompatible // indirect
2730
github.com/kr/pretty v0.3.1 // indirect
2831
github.com/kr/text v0.2.0 // indirect
2932
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
3033
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
3134
github.com/prometheus/procfs v0.9.0 // indirect
3235
github.com/rogpeppe/go-internal v1.9.0 // indirect
36+
github.com/smartystreets/assertions v1.13.1 // indirect
37+
github.com/smartystreets/goconvey v1.8.0 // indirect
3338
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
3439
golang.org/x/crypto v0.7.0 // indirect
3540
golang.org/x/net v0.8.0 // indirect

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
2+
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
13
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
24
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
35
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
@@ -26,8 +28,12 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
2628
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
2729
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
2830
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
31+
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
32+
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
2933
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
3034
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
35+
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
36+
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
3137
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
3238
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
3339
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -56,6 +62,10 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
5662
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
5763
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
5864
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
65+
github.com/smartystreets/assertions v1.13.1 h1:Ef7KhSmjZcK6AVf9YbJdvPYG9avaF0ZxudX+ThRdWfU=
66+
github.com/smartystreets/assertions v1.13.1/go.mod h1:cXr/IwVfSo/RbCSPhoAPv73p3hlSdrBH/b3SdnW/LMY=
67+
github.com/smartystreets/goconvey v1.8.0 h1:Oi49ha/2MURE0WexF052Z0m+BNSGirfjg5RL+JXWq3w=
68+
github.com/smartystreets/goconvey v1.8.0/go.mod h1:EdX8jtrTIj26jmjCOVNMVSIYAtgexqXKHOXW2Dx9JLg=
5969
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6070
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
6171
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=

0 commit comments

Comments
 (0)