Skip to content

Commit 443e086

Browse files
author
Pierre SOUCHAY
committed
Ensure collection returns within a specified delay
**Context**: As explained in #1228, when database is very slow to answer, every call to prometheus exporter might consume a new connection and possibly consume all available connections **Solution**: Ensure a Context with a specified Timeout is specified, so the connection will end if duration of collection is too long
1 parent 7c167f7 commit 443e086

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

cmd/postgres_exporter/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ var (
5050
excludeDatabases = kingpin.Flag("exclude-databases", "A list of databases to remove when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXCLUDE_DATABASES").String()
5151
includeDatabases = kingpin.Flag("include-databases", "A list of databases to include when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_INCLUDE_DATABASES").String()
5252
metricPrefix = kingpin.Flag("metric-prefix", "A metric prefix can be used to have non-default (not \"pg\") prefixes for each of the metrics").Default("pg").Envar("PG_EXPORTER_METRIC_PREFIX").String()
53+
collectionTimeout = kingpin.Flag("collection-timeout", "Maximum duration of collection").Default("1m").Envar("PG_EXPORTER_COLLECTION_TIMEOUT").String()
5354
logger = promslog.NewNopLogger()
5455
)
5556

@@ -137,7 +138,7 @@ func main() {
137138
excludedDatabases,
138139
dsn,
139140
[]string{},
140-
)
141+
collector.CollectionTimeout(*collectionTimeout))
141142
if err != nil {
142143
logger.Warn("Failed to create PostgresCollector", "err", err.Error())
143144
} else {

collector/collector.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ type PostgresCollector struct {
9292
Collectors map[string]Collector
9393
logger *slog.Logger
9494

95-
instance *instance
95+
instance *instance
96+
CollectionTimeout time.Duration
9697
}
9798

9899
type Option func(*PostgresCollector) error
@@ -158,6 +159,17 @@ func NewPostgresCollector(logger *slog.Logger, excludeDatabases []string, dsn st
158159
return p, nil
159160
}
160161

162+
func CollectionTimeout(s string) Option {
163+
return func(e *PostgresCollector) error {
164+
duration, err := time.ParseDuration(s)
165+
if err != nil {
166+
return err
167+
}
168+
e.CollectionTimeout = duration
169+
return nil
170+
}
171+
}
172+
161173
// Describe implements the prometheus.Collector interface.
162174
func (p PostgresCollector) Describe(ch chan<- *prometheus.Desc) {
163175
ch <- scrapeDurationDesc
@@ -166,8 +178,8 @@ func (p PostgresCollector) Describe(ch chan<- *prometheus.Desc) {
166178

167179
// Collect implements the prometheus.Collector interface.
168180
func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) {
169-
ctx := context.TODO()
170-
181+
ctx, cancel := context.WithTimeout(context.Background(), p.CollectionTimeout)
182+
defer cancel()
171183
// copy the instance so that concurrent scrapes have independent instances
172184
inst := p.instance.copy()
173185

0 commit comments

Comments
 (0)