3838 Help : "How many MySQL connections and what status they're in." ,
3939 }, []string {"state" })
4040
41+ mysqlConnectionsCounters = kitprom .NewGaugeFrom (stdprom.GaugeOpts {
42+ Name : "mysql_connections_counters" ,
43+ Help : `Counters specific to the sql connections.
44+ wait_count: The total number of connections waited for.
45+ wait_duration: The total time blocked waiting for a new connection.
46+ max_idle_closed: The total number of connections closed due to SetMaxIdleConns.
47+ max_idle_time_closed: The total number of connections closed due to SetConnMaxIdleTime.
48+ max_lifetime_closed: The total number of connections closed due to SetConnMaxLifetime.
49+ ` ,
50+ }, []string {"counter" })
51+
4152 // mySQLErrDuplicateKey is the error code for duplicate entries
4253 // https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.html#error_er_dup_entry
4354 mySQLErrDuplicateKey uint16 = 1062
@@ -65,14 +76,18 @@ type mysql struct {
6576 logger log.Logger
6677 tls * tls.Config
6778
79+ db * sql.DB
80+
6881 connections * kitprom.Gauge
82+ counters * kitprom.Gauge
6983}
7084
7185func (my * mysql ) Connect (ctx context.Context ) (* sql.DB , error ) {
7286 db , err := sql .Open ("mysql" , my .dsn )
7387 if err != nil {
7488 return nil , err
7589 }
90+
7691 db .SetMaxOpenConns (maxActiveMySQLConnections )
7792
7893 // Check out DB is up and working
@@ -88,17 +103,33 @@ func (my *mysql) Connect(ctx context.Context) (*sql.DB, error) {
88103 case <- ctx .Done ():
89104 return
90105 case <- t .C :
91- stats := db .Stats ()
92- my .connections .With ("state" , "idle" ).Set (float64 (stats .Idle ))
93- my .connections .With ("state" , "inuse" ).Set (float64 (stats .InUse ))
94- my .connections .With ("state" , "open" ).Set (float64 (stats .OpenConnections ))
106+ my .RecordStats ()
95107 }
96108 }
97109 }()
98110
111+ my .db = db
99112 return db , nil
100113}
101114
115+ func (my * mysql ) RecordStats () error {
116+ if my .db == nil {
117+ return errors .New ("database not connected" )
118+ }
119+
120+ stats := my .db .Stats ()
121+ my .connections .With ("state" , "idle" ).Set (float64 (stats .Idle ))
122+ my .connections .With ("state" , "inuse" ).Set (float64 (stats .InUse ))
123+ my .connections .With ("state" , "open" ).Set (float64 (stats .OpenConnections ))
124+ my .counters .With ("counter" , "wait_count" ).Set (float64 (stats .WaitCount ))
125+ my .counters .With ("counter" , "wait_ms" ).Set (float64 (stats .WaitDuration .Milliseconds ()))
126+ my .counters .With ("counter" , "max_idle_closed" ).Set (float64 (stats .MaxIdleClosed ))
127+ my .counters .With ("counter" , "max_idle_time_closed" ).Set (float64 (stats .MaxIdleTimeClosed ))
128+ my .counters .With ("counter" , "max_lifetime_closed" ).Set (float64 (stats .MaxLifetimeClosed ))
129+
130+ return nil
131+ }
132+
102133func mysqlConnection (logger log.Logger , mysqlConfig * MySQLConfig , databaseName string ) (* mysql , error ) {
103134 timeout := "30s"
104135 if v := os .Getenv ("MYSQL_TIMEOUT" ); v != "" {
@@ -142,7 +173,7 @@ func mysqlConnection(logger log.Logger, mysqlConfig *MySQLConfig, databaseName s
142173 logger .Logf ("verifying MySQL server certificate using CA from file %s" , mysqlConfig .TLSCAFile )
143174 _ , err := state .PeerCertificates [0 ].Verify (x509.VerifyOptions {Roots : rootCertPool })
144175 if err != nil {
145- return err
176+ return logger . Error (). LogError ( err ). Err ()
146177 }
147178 return nil
148179 }
@@ -166,6 +197,7 @@ func mysqlConnection(logger log.Logger, mysqlConfig *MySQLConfig, databaseName s
166197 logger : logger ,
167198 tls : tlsConfig ,
168199 connections : mysqlConnections ,
200+ counters : mysqlConnectionsCounters ,
169201 }, nil
170202}
171203
0 commit comments