Skip to content

Commit 9ae6002

Browse files
Warmup the connection pool per database (#264)
Warmup the connection pool per database Signed-off-by: Anders Swanson <anders.swanson@oracle.com>
1 parent bd00cc6 commit 9ae6002

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

collector/collector.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,18 @@ func maskDsn(dsn string) string {
4949
// NewExporter creates a new Exporter instance
5050
func NewExporter(logger *slog.Logger, m *MetricsConfiguration) *Exporter {
5151
var databases []*Database
52+
wg := &sync.WaitGroup{}
5253
for dbname, dbconfig := range m.Databases {
53-
databases = append(databases, NewDatabase(logger, dbname, dbconfig))
54+
logger.Info("Initializing database", "database", dbname)
55+
database := NewDatabase(logger, dbname, dbconfig)
56+
databases = append(databases, database)
57+
wg.Add(1)
58+
go func() {
59+
defer wg.Done()
60+
database.WarmupConnectionPool(logger)
61+
}()
5462
}
63+
wg.Wait()
5564
e := &Exporter{
5665
mu: &sync.Mutex{},
5766
duration: prometheus.NewGauge(prometheus.GaugeOpts{

collector/database.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package collector
55

66
import (
7+
"context"
78
"database/sql"
89
"fmt"
910
"github.com/godror/godror"
@@ -64,7 +65,6 @@ func (d *Database) constLabels() map[string]string {
6465

6566
func NewDatabase(logger *slog.Logger, dbname string, dbconfig DatabaseConfig) *Database {
6667
db, dbtype := connect(logger, dbname, dbconfig)
67-
6868
return &Database{
6969
Name: dbname,
7070
Up: 0,
@@ -74,6 +74,42 @@ func NewDatabase(logger *slog.Logger, dbname string, dbconfig DatabaseConfig) *D
7474
}
7575
}
7676

77+
// WarmupConnectionPool serially acquires connections to "warm up" the connection pool.
78+
// This is a workaround for a perceived bug in ODPI_C where rapid acquisition of connections
79+
// results in a SIGABRT.
80+
func (d *Database) WarmupConnectionPool(logger *slog.Logger) {
81+
var connections []*sql.Conn
82+
poolSize := d.Config.GetMaxOpenConns()
83+
if poolSize < 1 {
84+
poolSize = d.Config.GetPoolMaxConnections()
85+
}
86+
if poolSize > 100 { // defensively cap poolsize
87+
poolSize = 100
88+
}
89+
warmup := func(i int) {
90+
time.Sleep(100 * time.Millisecond)
91+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
92+
defer cancel()
93+
94+
conn, err := d.Session.Conn(ctx)
95+
if err != nil {
96+
logger.Debug("Failed to open database connection on warmup", "conn", i, "error", err, "database", d.Name)
97+
return
98+
}
99+
connections = append(connections, conn)
100+
}
101+
for i := 0; i < poolSize; i++ {
102+
warmup(i + 1)
103+
}
104+
105+
logger.Debug("Warmed connection pool", "total", len(connections), "database", d.Name)
106+
for i, conn := range connections {
107+
if err := conn.Close(); err != nil {
108+
logger.Debug("Failed to return database connection to pool on warmup", "conn", i+1, "error", err, "database", d.Name)
109+
}
110+
}
111+
}
112+
77113
func connect(logger *slog.Logger, dbname string, dbconfig DatabaseConfig) (*sql.DB, float64) {
78114
logger.Debug("Launching connection to "+maskDsn(dbconfig.URL), "database", dbname)
79115

main.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,7 @@ func main() {
110110
logger.Error("unable to load metrics configuration", "error", err)
111111
return
112112
}
113-
114-
for dbname, db := range m.Databases {
115-
if db.GetMaxOpenConns() > 0 {
116-
logger.Info(dbname + " database max idle connections is greater than 0, so will use go-sql connection pool and pooling settings will be ignored")
117-
} else {
118-
logger.Info(dbname + " database max idle connections is 0, so will use Oracle connection pool. Tune with database pooling settings")
119-
}
120-
}
113+
121114
exporter := collector.NewExporter(logger, m)
122115
if exporter.ScrapeInterval() != 0 {
123116
ctx, cancel := context.WithCancel(context.Background())

0 commit comments

Comments
 (0)