boulder/sa/metrics.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)
}