You've already forked postgres_exporter
							
							
				mirror of
				https://github.com/prometheus-community/postgres_exporter.git
				synced 2025-11-03 07:53:12 +03:00 
			
		
		
		
	Delay database connection until scrape (#882)
This no longer returns an error when creating a collector.instance when the database cannot be reached for the version query. This will resolve the entire postgresCollector not being registered for metrics collection when a database is not available. If the version query fails, the scrape will fail. Resolves #880 Signed-off-by: Joe Adams <github@joeadams.io>
This commit is contained in:
		@@ -166,6 +166,14 @@ func (p PostgresCollector) Describe(ch chan<- *prometheus.Desc) {
 | 
				
			|||||||
// Collect implements the prometheus.Collector interface.
 | 
					// Collect implements the prometheus.Collector interface.
 | 
				
			||||||
func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) {
 | 
					func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) {
 | 
				
			||||||
	ctx := context.TODO()
 | 
						ctx := context.TODO()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set up the database connection for the collector.
 | 
				
			||||||
 | 
						err := p.instance.setup()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							level.Error(p.logger).Log("msg", "Error opening connection to database", "err", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wg := sync.WaitGroup{}
 | 
						wg := sync.WaitGroup{}
 | 
				
			||||||
	wg.Add(len(p.Collectors))
 | 
						wg.Add(len(p.Collectors))
 | 
				
			||||||
	for name, c := range p.Collectors {
 | 
						for name, c := range p.Collectors {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,29 +22,43 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type instance struct {
 | 
					type instance struct {
 | 
				
			||||||
 | 
						dsn     string
 | 
				
			||||||
	db      *sql.DB
 | 
						db      *sql.DB
 | 
				
			||||||
	version semver.Version
 | 
						version semver.Version
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newInstance(dsn string) (*instance, error) {
 | 
					func newInstance(dsn string) (*instance, error) {
 | 
				
			||||||
	i := &instance{}
 | 
						i := &instance{
 | 
				
			||||||
 | 
							dsn: dsn,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// "Create" a database handle to verify the DSN provided is valid.
 | 
				
			||||||
 | 
						// Open is not guaranteed to create a connection.
 | 
				
			||||||
	db, err := sql.Open("postgres", dsn)
 | 
						db, err := sql.Open("postgres", dsn)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						db.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return i, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *instance) setup() error {
 | 
				
			||||||
 | 
						db, err := sql.Open("postgres", i.dsn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	db.SetMaxOpenConns(1)
 | 
						db.SetMaxOpenConns(1)
 | 
				
			||||||
	db.SetMaxIdleConns(1)
 | 
						db.SetMaxIdleConns(1)
 | 
				
			||||||
	i.db = db
 | 
						i.db = db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version, err := queryVersion(db)
 | 
						version, err := queryVersion(i.db)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		db.Close()
 | 
							return fmt.Errorf("error querying postgresql version: %w", err)
 | 
				
			||||||
		return nil, err
 | 
						} else {
 | 
				
			||||||
 | 
							i.version = version
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
	i.version = version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return i, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (i *instance) getDB() *sql.DB {
 | 
					func (i *instance) getDB() *sql.DB {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-kit/log"
 | 
						"github.com/go-kit/log"
 | 
				
			||||||
 | 
						"github.com/go-kit/log/level"
 | 
				
			||||||
	"github.com/prometheus-community/postgres_exporter/config"
 | 
						"github.com/prometheus-community/postgres_exporter/config"
 | 
				
			||||||
	"github.com/prometheus/client_golang/prometheus"
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -74,6 +75,13 @@ func (pc *ProbeCollector) Describe(ch chan<- *prometheus.Desc) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pc *ProbeCollector) Collect(ch chan<- prometheus.Metric) {
 | 
					func (pc *ProbeCollector) Collect(ch chan<- prometheus.Metric) {
 | 
				
			||||||
 | 
						// Set up the database connection for the collector.
 | 
				
			||||||
 | 
						err := pc.instance.setup()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							level.Error(pc.logger).Log("msg", "Error opening connection to database", "err", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wg := sync.WaitGroup{}
 | 
						wg := sync.WaitGroup{}
 | 
				
			||||||
	wg.Add(len(pc.collectors))
 | 
						wg.Add(len(pc.collectors))
 | 
				
			||||||
	for name, c := range pc.collectors {
 | 
						for name, c := range pc.collectors {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user