mirror of
https://github.com/prometheus-community/postgres_exporter
synced 2025-04-04 23:29:30 +00:00
Fix pg_up metric returns last calculated value without explicit resetting (#291)
If exporter is scraped by multiple Prometheuses (as we do) - Collect() could be called concurrently. In result in some cases one of Prometheuses could get pg_up = 0, because it was explicitly set to zero on first Collect call.
This commit is contained in:
parent
1ab8d2bbc8
commit
238f5c099a
@ -129,6 +129,16 @@ type MetricMap struct {
|
|||||||
conversion func(interface{}) (float64, bool) // Conversion function to turn PG result into float64
|
conversion func(interface{}) (float64, bool) // Conversion function to turn PG result into float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorConnectToServer is a connection to PgSQL server error
|
||||||
|
type ErrorConnectToServer struct {
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns error
|
||||||
|
func (e *ErrorConnectToServer) Error() string {
|
||||||
|
return e.Msg
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: revisit this with the semver system
|
// TODO: revisit this with the semver system
|
||||||
func dumpMaps() {
|
func dumpMaps() {
|
||||||
// TODO: make this function part of the exporter
|
// TODO: make this function part of the exporter
|
||||||
@ -813,21 +823,24 @@ func (s *Server) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scrape loads metrics.
|
// Scrape loads metrics.
|
||||||
func (s *Server) Scrape(ch chan<- prometheus.Metric, errGauge prometheus.Gauge, disableSettingsMetrics bool) {
|
func (s *Server) Scrape(ch chan<- prometheus.Metric, disableSettingsMetrics bool) error {
|
||||||
s.mappingMtx.RLock()
|
s.mappingMtx.RLock()
|
||||||
defer s.mappingMtx.RUnlock()
|
defer s.mappingMtx.RUnlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
if !disableSettingsMetrics {
|
if !disableSettingsMetrics {
|
||||||
if err := querySettings(ch, s); err != nil {
|
if err = querySettings(ch, s); err != nil {
|
||||||
log.Errorf("Error retrieving settings: %s", err)
|
err = fmt.Errorf("error retrieving settings: %s", err)
|
||||||
errGauge.Inc()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errMap := queryNamespaceMappings(ch, s)
|
errMap := queryNamespaceMappings(ch, s)
|
||||||
if len(errMap) > 0 {
|
if len(errMap) > 0 {
|
||||||
errGauge.Inc()
|
err = fmt.Errorf("queryNamespaceMappings returned %d errors", len(errMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Servers contains a collection of servers to Postgres.
|
// Servers contains a collection of servers to Postgres.
|
||||||
@ -1289,16 +1302,40 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
|
|||||||
e.duration.Set(time.Since(begun).Seconds())
|
e.duration.Set(time.Since(begun).Seconds())
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
e.error.Set(0)
|
|
||||||
e.psqlUp.Set(0)
|
|
||||||
e.totalScrapes.Inc()
|
e.totalScrapes.Inc()
|
||||||
|
|
||||||
dsns := e.dsn
|
dsns := e.dsn
|
||||||
if e.autoDiscoverDatabases {
|
if e.autoDiscoverDatabases {
|
||||||
dsns = e.discoverDatabaseDSNs()
|
dsns = e.discoverDatabaseDSNs()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errorsCount int
|
||||||
|
var connectionErrorsCount int
|
||||||
|
|
||||||
for _, dsn := range dsns {
|
for _, dsn := range dsns {
|
||||||
e.scrapeDSN(ch, dsn)
|
if err := e.scrapeDSN(ch, dsn); err != nil {
|
||||||
|
errorsCount++
|
||||||
|
|
||||||
|
log.Errorf(err.Error())
|
||||||
|
|
||||||
|
if _, ok := err.(*ErrorConnectToServer); ok {
|
||||||
|
connectionErrorsCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case connectionErrorsCount >= len(dsns):
|
||||||
|
e.psqlUp.Set(0)
|
||||||
|
default:
|
||||||
|
e.psqlUp.Set(1) // Didn't fail, can mark connection as up for this scrape.
|
||||||
|
}
|
||||||
|
|
||||||
|
switch errorsCount {
|
||||||
|
case 0:
|
||||||
|
e.error.Set(0)
|
||||||
|
default:
|
||||||
|
e.error.Set(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,24 +1379,18 @@ func (e *Exporter) discoverDatabaseDSNs() []string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exporter) scrapeDSN(ch chan<- prometheus.Metric, dsn string) {
|
func (e *Exporter) scrapeDSN(ch chan<- prometheus.Metric, dsn string) error {
|
||||||
server, err := e.servers.GetServer(dsn)
|
server, err := e.servers.GetServer(dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error opening connection to database (%s): %v", loggableDSN(dsn), err)
|
return &ErrorConnectToServer{fmt.Sprintf("Error opening connection to database (%s): %s", loggableDSN(dsn), err)}
|
||||||
e.error.Inc()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Didn't fail, can mark connection as up for this scrape.
|
|
||||||
e.psqlUp.Inc()
|
|
||||||
|
|
||||||
// Check if map versions need to be updated
|
// Check if map versions need to be updated
|
||||||
if err := e.checkMapVersions(ch, server); err != nil {
|
if err := e.checkMapVersions(ch, server); err != nil {
|
||||||
log.Warnln("Proceeding with outdated query maps, as the Postgres version could not be determined:", err)
|
log.Warnln("Proceeding with outdated query maps, as the Postgres version could not be determined:", err)
|
||||||
e.error.Inc()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Scrape(ch, e.error, e.disableSettingsMetrics)
|
return server.Scrape(ch, e.disableSettingsMetrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to get the DataSource
|
// try to get the DataSource
|
||||||
|
Loading…
Reference in New Issue
Block a user