131 lines
4.3 KiB
Go
131 lines
4.3 KiB
Go
package sa
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
)
|
|
|
|
type dbMetricsCollector struct {
|
|
db *sql.DB
|
|
dbSettings DbSettings
|
|
|
|
maxOpenConns *prometheus.Desc
|
|
maxIdleConns *prometheus.Desc
|
|
connMaxLifetime *prometheus.Desc
|
|
connMaxIdleTime *prometheus.Desc
|
|
openConns *prometheus.Desc
|
|
inUse *prometheus.Desc
|
|
idle *prometheus.Desc
|
|
waitCount *prometheus.Desc
|
|
waitDuration *prometheus.Desc
|
|
maxIdleClosed *prometheus.Desc
|
|
maxLifetimeClosed *prometheus.Desc
|
|
}
|
|
|
|
// Describe is implemented with DescribeByCollect. That's possible because the
|
|
// Collect method will always return the same metrics with the same descriptors.
|
|
func (dbc dbMetricsCollector) Describe(ch chan<- *prometheus.Desc) {
|
|
prometheus.DescribeByCollect(dbc, ch)
|
|
}
|
|
|
|
// Collect first triggers the dbMaps's sql.Db's Stats function. Then it
|
|
// creates constant metrics for each DBStats value on the fly based on the
|
|
// returned data.
|
|
//
|
|
// Note that Collect could be called concurrently, so we depend on
|
|
// Stats() to be concurrency-safe.
|
|
func (dbc dbMetricsCollector) Collect(ch chan<- prometheus.Metric) {
|
|
writeStat := func(stat *prometheus.Desc, typ prometheus.ValueType, val float64) {
|
|
ch <- prometheus.MustNewConstMetric(stat, typ, val)
|
|
}
|
|
writeCounter := func(stat *prometheus.Desc, val float64) {
|
|
writeStat(stat, prometheus.CounterValue, val)
|
|
}
|
|
writeGauge := func(stat *prometheus.Desc, val float64) {
|
|
writeStat(stat, prometheus.GaugeValue, val)
|
|
}
|
|
|
|
// Translate the DBMap's db.DBStats counter values into Prometheus metrics.
|
|
dbMapStats := dbc.db.Stats()
|
|
writeGauge(dbc.maxOpenConns, float64(dbMapStats.MaxOpenConnections))
|
|
writeGauge(dbc.maxIdleConns, float64(dbc.dbSettings.MaxIdleConns))
|
|
writeGauge(dbc.connMaxLifetime, float64(dbc.dbSettings.ConnMaxLifetime))
|
|
writeGauge(dbc.connMaxIdleTime, float64(dbc.dbSettings.ConnMaxIdleTime))
|
|
writeGauge(dbc.openConns, float64(dbMapStats.OpenConnections))
|
|
writeGauge(dbc.inUse, float64(dbMapStats.InUse))
|
|
writeGauge(dbc.idle, float64(dbMapStats.Idle))
|
|
writeCounter(dbc.waitCount, float64(dbMapStats.WaitCount))
|
|
writeCounter(dbc.waitDuration, dbMapStats.WaitDuration.Seconds())
|
|
writeCounter(dbc.maxIdleClosed, float64(dbMapStats.MaxIdleClosed))
|
|
writeCounter(dbc.maxLifetimeClosed, float64(dbMapStats.MaxLifetimeClosed))
|
|
}
|
|
|
|
// initDBMetrics will register a Collector that translates the provided dbMap's
|
|
// stats and DbSettings into Prometheus metrics on the fly. The exported metrics
|
|
// all start with `db_`. The underlying data comes from sql.DBStats:
|
|
// https://pkg.go.dev/database/sql#DBStats
|
|
func initDBMetrics(db *sql.DB, stats prometheus.Registerer, dbSettings DbSettings, address string, user string) error {
|
|
// Create a dbMetricsCollector and register it
|
|
dbc := dbMetricsCollector{db: db, dbSettings: dbSettings}
|
|
|
|
labels := prometheus.Labels{"address": address, "user": user}
|
|
|
|
dbc.maxOpenConns = prometheus.NewDesc(
|
|
"db_max_open_connections",
|
|
"Maximum number of DB connections allowed.",
|
|
nil, labels)
|
|
|
|
dbc.maxIdleConns = prometheus.NewDesc(
|
|
"db_max_idle_connections",
|
|
"Maximum number of idle DB connections allowed.",
|
|
nil, labels)
|
|
|
|
dbc.connMaxLifetime = prometheus.NewDesc(
|
|
"db_connection_max_lifetime",
|
|
"Maximum lifetime of DB connections allowed.",
|
|
nil, labels)
|
|
|
|
dbc.connMaxIdleTime = prometheus.NewDesc(
|
|
"db_connection_max_idle_time",
|
|
"Maximum lifetime of idle DB connections allowed.",
|
|
nil, labels)
|
|
|
|
dbc.openConns = prometheus.NewDesc(
|
|
"db_open_connections",
|
|
"Number of established DB connections (in-use and idle).",
|
|
nil, labels)
|
|
|
|
dbc.inUse = prometheus.NewDesc(
|
|
"db_inuse",
|
|
"Number of DB connections currently in use.",
|
|
nil, labels)
|
|
|
|
dbc.idle = prometheus.NewDesc(
|
|
"db_idle",
|
|
"Number of idle DB connections.",
|
|
nil, labels)
|
|
|
|
dbc.waitCount = prometheus.NewDesc(
|
|
"db_wait_count",
|
|
"Total number of DB connections waited for.",
|
|
nil, labels)
|
|
|
|
dbc.waitDuration = prometheus.NewDesc(
|
|
"db_wait_duration_seconds",
|
|
"The total time blocked waiting for a new connection.",
|
|
nil, labels)
|
|
|
|
dbc.maxIdleClosed = prometheus.NewDesc(
|
|
"db_max_idle_closed",
|
|
"Total number of connections closed due to SetMaxIdleConns.",
|
|
nil, labels)
|
|
|
|
dbc.maxLifetimeClosed = prometheus.NewDesc(
|
|
"db_max_lifetime_closed",
|
|
"Total number of connections closed due to SetConnMaxLifetime.",
|
|
nil, labels)
|
|
|
|
return stats.Register(dbc)
|
|
}
|