metrics/sqlmetrics/dbstats.go (182 lines of code) (raw):

package sqlmetrics import ( "database/sql" "github.com/prometheus/client_golang/prometheus" ) const ( namespace = "go_sql_dbstats" subsystem = "connections" dbNameLabel = "db_name" // Names for the recorded metrics. maxOpenConnectionsName = "max_open" openConnectionsName = "open" inUseName = "in_use" idleName = "idle" waitCountName = "waits_total" waitDurationName = "wait_seconds_total" maxIdleClosedName = "max_idle_closed_count_total" maxIdleTimeClosedName = "max_idle_time_closed_count_total" maxLifetimeClosedName = "max_lifetime_closed_count_total" // Descriptions for the recorded metrics. maxOpenConnectionsDesc = "The limit of open connections to the database." openConnectionsDesc = "The number of established connections both in use and idle." inUseDesc = "The number of connections currently in use." idleDesc = "The number of idle connections." waitCountDesc = "The total number of connections waited for." waitDurationDesc = "The total time blocked waiting for a new connection." maxIdleClosedDesc = "The total number of connections closed due to SetMaxIdleConns." maxIdleTimeClosedDesc = "The total number of connections closed due to SetConnMaxIdleTime." maxLifetimeClosedDesc = "The total number of connections closed due to SetConnMaxLifetime." ) // DBStatsGetter is an interface for sql.DBStats. It's implemented by sql.DB. type DBStatsGetter interface { Stats() sql.DBStats } // DBStatsCollector implements the prometheus.Collector interface. type DBStatsCollector struct { sg DBStatsGetter maxOpenDesc *prometheus.Desc openDesc *prometheus.Desc inUseDesc *prometheus.Desc idleDesc *prometheus.Desc waitCountDesc *prometheus.Desc waitDurationDesc *prometheus.Desc maxIdleClosedDesc *prometheus.Desc maxIdleTimeClosedDesc *prometheus.Desc maxLifetimeClosedDesc *prometheus.Desc } // Describe implements the prometheus.Collector interface. func (c *DBStatsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.maxOpenDesc ch <- c.openDesc ch <- c.inUseDesc ch <- c.idleDesc ch <- c.waitCountDesc ch <- c.waitDurationDesc ch <- c.maxIdleClosedDesc ch <- c.maxIdleTimeClosedDesc ch <- c.maxLifetimeClosedDesc } // Collect implements the prometheus.Collector interface. func (c *DBStatsCollector) Collect(ch chan<- prometheus.Metric) { stats := c.sg.Stats() ch <- prometheus.MustNewConstMetric( c.maxOpenDesc, prometheus.GaugeValue, float64(stats.MaxOpenConnections), ) ch <- prometheus.MustNewConstMetric( c.openDesc, prometheus.GaugeValue, float64(stats.OpenConnections), ) ch <- prometheus.MustNewConstMetric( c.inUseDesc, prometheus.GaugeValue, float64(stats.InUse), ) ch <- prometheus.MustNewConstMetric( c.idleDesc, prometheus.GaugeValue, float64(stats.Idle), ) ch <- prometheus.MustNewConstMetric( c.waitCountDesc, prometheus.CounterValue, float64(stats.WaitCount), ) ch <- prometheus.MustNewConstMetric( c.waitDurationDesc, prometheus.CounterValue, stats.WaitDuration.Seconds(), ) ch <- prometheus.MustNewConstMetric( c.maxIdleClosedDesc, prometheus.CounterValue, float64(stats.MaxIdleClosed), ) ch <- prometheus.MustNewConstMetric( c.maxIdleTimeClosedDesc, prometheus.CounterValue, float64(stats.MaxIdleTimeClosed), ) ch <- prometheus.MustNewConstMetric( c.maxLifetimeClosedDesc, prometheus.CounterValue, float64(stats.MaxLifetimeClosed), ) } type dbStatsCollectorConfig struct { extraLabels prometheus.Labels } // DBStatsCollectorOption is used to pass options in NewDBStatsCollector. type DBStatsCollectorOption func(*dbStatsCollectorConfig) // WithExtraLabels will configure extra label values to apply to the DBStats metrics. // A label named db_name will be ignored, as this is set internally. func WithExtraLabels(labelValues map[string]string) DBStatsCollectorOption { return func(config *dbStatsCollectorConfig) { config.extraLabels = labelValues } } func applyDBStatsCollectorOptions(opts []DBStatsCollectorOption) dbStatsCollectorConfig { config := dbStatsCollectorConfig{} for _, v := range opts { v(&config) } return config } // NewDBStatsCollector creates a new DBStatsCollector. func NewDBStatsCollector(dbName string, sg DBStatsGetter, opts ...DBStatsCollectorOption) *DBStatsCollector { config := applyDBStatsCollectorOptions(opts) if config.extraLabels == nil { config.extraLabels = make(prometheus.Labels) } config.extraLabels[dbNameLabel] = dbName return &DBStatsCollector{ sg: sg, maxOpenDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, maxOpenConnectionsName), maxOpenConnectionsDesc, nil, config.extraLabels, ), openDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, openConnectionsName), openConnectionsDesc, nil, config.extraLabels, ), inUseDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, inUseName), inUseDesc, nil, config.extraLabels, ), idleDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, idleName), idleDesc, nil, config.extraLabels, ), waitCountDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, waitCountName), waitCountDesc, nil, config.extraLabels, ), waitDurationDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, waitDurationName), waitDurationDesc, nil, config.extraLabels, ), maxIdleClosedDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, maxIdleClosedName), maxIdleClosedDesc, nil, config.extraLabels, ), maxIdleTimeClosedDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, maxIdleTimeClosedName), maxIdleTimeClosedDesc, nil, config.extraLabels, ), maxLifetimeClosedDesc: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, maxLifetimeClosedName), maxLifetimeClosedDesc, nil, config.extraLabels, ), } }