Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions cmd/postgres_exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
package main

import (
"fmt"
"net/http"
"os"
"strings"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
Expand Down Expand Up @@ -101,13 +103,16 @@ func main() {
os.Exit(1)
}

excludedDatabases := strings.Split(*excludeDatabases, ",")
logger.Log("msg", "Excluded databases", "databases", fmt.Sprintf("%v", excludedDatabases))

opts := []ExporterOpt{
DisableDefaultMetrics(*disableDefaultMetrics),
DisableSettingsMetrics(*disableSettingsMetrics),
AutoDiscoverDatabases(*autoDiscoverDatabases),
WithUserQueriesPath(*queriesPath),
WithConstantLabels(*constantLabelsList),
ExcludeDatabases(*excludeDatabases),
ExcludeDatabases(excludedDatabases),
IncludeDatabases(*includeDatabases),
}

Expand All @@ -128,6 +133,7 @@ func main() {

pe, err := collector.NewPostgresCollector(
logger,
excludedDatabases,
dsn,
[]string{},
)
Expand All @@ -143,7 +149,7 @@ func main() {
w.Write(landingPage) // nolint: errcheck
})

http.HandleFunc("/probe", handleProbe(logger))
http.HandleFunc("/probe", handleProbe(logger, excludedDatabases))

srv := &http.Server{}
if err := web.ListenAndServe(srv, webConfig, logger); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/postgres_exporter/postgres_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,9 +484,9 @@ func AutoDiscoverDatabases(b bool) ExporterOpt {
}

// ExcludeDatabases allows to filter out result from AutoDiscoverDatabases
func ExcludeDatabases(s string) ExporterOpt {
func ExcludeDatabases(s []string) ExporterOpt {
return func(e *Exporter) {
e.excludeDatabases = strings.Split(s, ",")
e.excludeDatabases = s
}
}

Expand Down
25 changes: 3 additions & 22 deletions cmd/postgres_exporter/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package main
import (
"fmt"
"net/http"
"time"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
Expand All @@ -26,7 +25,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
)

func handleProbe(logger log.Logger) http.HandlerFunc {
func handleProbe(logger log.Logger, excludeDatabases []string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
conf := c.GetConfig()
Expand Down Expand Up @@ -62,29 +61,17 @@ func handleProbe(logger log.Logger) http.HandlerFunc {

// TODO(@sysadmind): Timeout

probeSuccessGauge := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "probe_success",
Help: "Displays whether or not the probe was a success",
})
probeDurationGauge := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "probe_duration_seconds",
Help: "Returns how long the probe took to complete in seconds",
})

tl := log.With(logger, "target", target)

start := time.Now()
registry := prometheus.NewRegistry()
registry.MustRegister(probeSuccessGauge)
registry.MustRegister(probeDurationGauge)

opts := []ExporterOpt{
DisableDefaultMetrics(*disableDefaultMetrics),
DisableSettingsMetrics(*disableSettingsMetrics),
AutoDiscoverDatabases(*autoDiscoverDatabases),
WithUserQueriesPath(*queriesPath),
WithConstantLabels(*constantLabelsList),
ExcludeDatabases(*excludeDatabases),
ExcludeDatabases(excludeDatabases),
IncludeDatabases(*includeDatabases),
}

Expand All @@ -96,10 +83,8 @@ func handleProbe(logger log.Logger) http.HandlerFunc {
registry.MustRegister(exporter)

// Run the probe
pc, err := collector.NewProbeCollector(tl, registry, dsn)
pc, err := collector.NewProbeCollector(tl, excludeDatabases, registry, dsn)
if err != nil {
probeSuccessGauge.Set(0)
probeDurationGauge.Set(time.Since(start).Seconds())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Expand All @@ -115,10 +100,6 @@ func handleProbe(logger log.Logger) http.HandlerFunc {

registry.MustRegister(pc)

duration := time.Since(start).Seconds()
probeDurationGauge.Set(duration)
probeSuccessGauge.Set(1)

// TODO check success, etc
h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
h.ServeHTTP(w, r)
Expand Down
16 changes: 12 additions & 4 deletions collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

var (
factories = make(map[string]func(logger log.Logger) (Collector, error))
factories = make(map[string]func(collectorConfig) (Collector, error))
initiatedCollectorsMtx = sync.Mutex{}
initiatedCollectors = make(map[string]Collector)
collectorState = make(map[string]*bool)
Expand Down Expand Up @@ -62,7 +62,12 @@ type Collector interface {
Update(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error
}

func registerCollector(name string, isDefaultEnabled bool, createFunc func(logger log.Logger) (Collector, error)) {
type collectorConfig struct {
logger log.Logger
excludeDatabases []string
}

func registerCollector(name string, isDefaultEnabled bool, createFunc func(collectorConfig) (Collector, error)) {
var helpDefaultState string
if isDefaultEnabled {
helpDefaultState = "enabled"
Expand Down Expand Up @@ -93,7 +98,7 @@ type PostgresCollector struct {
type Option func(*PostgresCollector) error

// NewPostgresCollector creates a new PostgresCollector.
func NewPostgresCollector(logger log.Logger, dsn string, filters []string, options ...Option) (*PostgresCollector, error) {
func NewPostgresCollector(logger log.Logger, excludeDatabases []string, dsn string, filters []string, options ...Option) (*PostgresCollector, error) {
p := &PostgresCollector{
logger: logger,
}
Expand Down Expand Up @@ -126,7 +131,10 @@ func NewPostgresCollector(logger log.Logger, dsn string, filters []string, optio
if collector, ok := initiatedCollectors[key]; ok {
collectors[key] = collector
} else {
collector, err := factories[key](log.With(logger, "collector", key))
collector, err := factories[key](collectorConfig{
logger: log.With(logger, "collector", key),
excludeDatabases: excludeDatabases,
})
if err != nil {
return nil, err
}
Expand Down
60 changes: 53 additions & 7 deletions collector/pg_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,19 @@ func init() {
}

type PGDatabaseCollector struct {
log log.Logger
log log.Logger
excludedDatabases []string
}

func NewPGDatabaseCollector(logger log.Logger) (Collector, error) {
return &PGDatabaseCollector{log: logger}, nil
func NewPGDatabaseCollector(config collectorConfig) (Collector, error) {
exclude := config.excludeDatabases
if exclude == nil {
exclude = []string{}
}
return &PGDatabaseCollector{
log: config.logger,
excludedDatabases: exclude,
}, nil
}

var pgDatabase = map[string]*prometheus.Desc{
Expand All @@ -41,20 +49,49 @@ var pgDatabase = map[string]*prometheus.Desc{
),
}

func (PGDatabaseCollector) Update(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
// Update implements Collector and exposes database size.
// It is called by the Prometheus registry when collecting metrics.
// The list of databases is retrieved from pg_database and filtered
// by the excludeDatabase config parameter. The tradeoff here is that
// we have to query the list of databases and then query the size of
// each database individually. This is because we can't filter the
// list of databases in the query because the list of excluded
// databases is dynamic.
func (c PGDatabaseCollector) Update(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
// Query the list of databases
rows, err := db.QueryContext(ctx,
`SELECT pg_database.datname
,pg_database_size(pg_database.datname)
FROM pg_database;`)
FROM pg_database;
`,
)
if err != nil {
return err
}
defer rows.Close()

var databases []string

for rows.Next() {
var datname string
if err := rows.Scan(&datname); err != nil {
return err
}

// Ignore excluded databases
// Filtering is done here instead of in the query to avoid
// a complicated NOT IN query with a variable number of parameters
if sliceContains(c.excludedDatabases, datname) {
continue
}

databases = append(databases, datname)
}

// Query the size of the databases
for _, datname := range databases {
var size int64
if err := rows.Scan(&datname, &size); err != nil {
err = db.QueryRowContext(ctx, "SELECT pg_database_size($1)", datname).Scan(&size)
if err != nil {
return err
}

Expand All @@ -68,3 +105,12 @@ func (PGDatabaseCollector) Update(ctx context.Context, db *sql.DB, ch chan<- pro
}
return nil
}

func sliceContains(slice []string, s string) bool {
for _, item := range slice {
if item == s {
return true
}
}
return false
}
3 changes: 1 addition & 2 deletions collector/pg_stat_bgwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"database/sql"
"time"

"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)

Expand All @@ -29,7 +28,7 @@ func init() {
type PGStatBGWriterCollector struct {
}

func NewPGStatBGWriterCollector(logger log.Logger) (Collector, error) {
func NewPGStatBGWriterCollector(collectorConfig) (Collector, error) {
return &PGStatBGWriterCollector{}, nil
}

Expand Down
8 changes: 6 additions & 2 deletions collector/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type ProbeCollector struct {
db *sql.DB
}

func NewProbeCollector(logger log.Logger, registry *prometheus.Registry, dsn config.DSN) (*ProbeCollector, error) {
func NewProbeCollector(logger log.Logger, excludeDatabases []string, registry *prometheus.Registry, dsn config.DSN) (*ProbeCollector, error) {
collectors := make(map[string]Collector)
initiatedCollectorsMtx.Lock()
defer initiatedCollectorsMtx.Unlock()
Expand All @@ -45,7 +45,11 @@ func NewProbeCollector(logger log.Logger, registry *prometheus.Registry, dsn con
if collector, ok := initiatedCollectors[key]; ok {
collectors[key] = collector
} else {
collector, err := factories[key](log.With(logger, "collector", key))
collector, err := factories[key](
collectorConfig{
logger: log.With(logger, "collector", key),
excludeDatabases: excludeDatabases,
})
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions collector/replication_slots.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type PGReplicationSlotCollector struct {
log log.Logger
}

func NewPGReplicationSlotCollector(logger log.Logger) (Collector, error) {
return &PGReplicationSlotCollector{log: logger}, nil
func NewPGReplicationSlotCollector(config collectorConfig) (Collector, error) {
return &PGReplicationSlotCollector{log: config.logger}, nil
}

var pgReplicationSlot = map[string]*prometheus.Desc{
Expand Down