@@ -15,10 +15,7 @@ package collector
1515
1616import (
1717 "context"
18- "database/sql"
1918 "fmt"
20- "regexp"
21- "strconv"
2219 "strings"
2320 "sync"
2421 "time"
@@ -38,18 +35,12 @@ const (
3835
3936// SQL queries and parameters.
4037const (
41- versionQuery = `SELECT @@version`
42-
4338 // System variable params formatting.
4439 // See: https://github.com/go-sql-driver/mysql#system-variables
4540 sessionSettingsParam = `log_slow_filter=%27tmp_table_on_disk,filesort_on_disk%27`
4641 timeoutParam = `lock_wait_timeout=%d`
4742)
4843
49- var (
50- versionRE = regexp .MustCompile (`^\d+\.\d+` )
51- )
52-
5344// Tunable flags.
5445var (
5546 exporterLockTimeout = kingpin .Flag (
@@ -92,6 +83,7 @@ type Exporter struct {
9283 logger log.Logger
9384 dsn string
9485 scrapers []Scraper
86+ instance * instance
9587}
9688
9789// New returns a new MySQL exporter for the provided DSN.
@@ -135,27 +127,23 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
135127func (e * Exporter ) scrape (ctx context.Context , ch chan <- prometheus.Metric ) float64 {
136128 var err error
137129 scrapeTime := time .Now ()
138- db , err := sql . Open ( "mysql" , e .dsn )
130+ instance , err := newInstance ( e .dsn )
139131 if err != nil {
140132 level .Error (e .logger ).Log ("msg" , "Error opening connection to database" , "err" , err )
141133 return 0.0
142134 }
143- defer db .Close ()
144-
145- // By design exporter should use maximum one connection per request.
146- db .SetMaxOpenConns (1 )
147- db .SetMaxIdleConns (1 )
148- // Set max lifetime for a connection.
149- db .SetConnMaxLifetime (1 * time .Minute )
135+ defer instance .Close ()
136+ e .instance = instance
150137
151- if err := db . PingContext ( ctx ); err != nil {
138+ if err := instance . Ping ( ); err != nil {
152139 level .Error (e .logger ).Log ("msg" , "Error pinging mysqld" , "err" , err )
153140 return 0.0
154141 }
155142
156143 ch <- prometheus .MustNewConstMetric (mysqlScrapeDurationSeconds , prometheus .GaugeValue , time .Since (scrapeTime ).Seconds (), "connection" )
157144
158- version := getMySQLVersion (db , e .logger )
145+ version := instance .versionMajorMinor
146+
159147 var wg sync.WaitGroup
160148 defer wg .Wait ()
161149 for _ , scraper := range e .scrapers {
@@ -169,7 +157,7 @@ func (e *Exporter) scrape(ctx context.Context, ch chan<- prometheus.Metric) floa
169157 label := "collect." + scraper .Name ()
170158 scrapeTime := time .Now ()
171159 collectorSuccess := 1.0
172- if err := scraper .Scrape (ctx , db , ch , log .With (e .logger , "scraper" , scraper .Name ())); err != nil {
160+ if err := scraper .Scrape (ctx , instance , ch , log .With (e .logger , "scraper" , scraper .Name ())); err != nil {
173161 level .Error (e .logger ).Log ("msg" , "Error from scraper" , "scraper" , scraper .Name (), "target" , e .getTargetFromDsn (), "err" , err )
174162 collectorSuccess = 0.0
175163 }
@@ -189,19 +177,3 @@ func (e *Exporter) getTargetFromDsn() string {
189177 }
190178 return dsnConfig .Addr
191179}
192-
193- func getMySQLVersion (db * sql.DB , logger log.Logger ) float64 {
194- var versionStr string
195- var versionNum float64
196- if err := db .QueryRow (versionQuery ).Scan (& versionStr ); err == nil {
197- versionNum , _ = strconv .ParseFloat (versionRE .FindString (versionStr ), 64 )
198- } else {
199- level .Debug (logger ).Log ("msg" , "Error querying version" , "err" , err )
200- }
201- // If we can't match/parse the version, set it some big value that matches all versions.
202- if versionNum == 0 {
203- level .Debug (logger ).Log ("msg" , "Error parsing version string" , "version" , versionStr )
204- versionNum = 999
205- }
206- return versionNum
207- }
0 commit comments