package metrics import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" ) // poolCollector reports the database connection pool's statistics on every scrape. type poolCollector struct { pool *pgxpool.Pool acquiredConns *prometheus.Desc idleConns *prometheus.Desc totalConns *prometheus.Desc maxConns *prometheus.Desc acquires *prometheus.Desc acquireWait *prometheus.Desc emptyAcquires *prometheus.Desc canceledAcquires *prometheus.Desc newConns *prometheus.Desc maxLifetimeDestroyed *prometheus.Desc maxIdleDestroyed *prometheus.Desc } // NewPoolCollector returns a collector for the musicserver_db_pool_* metrics of pool. // Register it once, for example with prometheus.MustRegister. func NewPoolCollector(pool *pgxpool.Pool) prometheus.Collector { desc := func(name, help string) *prometheus.Desc { return prometheus.NewDesc("musicserver_db_pool_"+name, help, nil, nil) } return &poolCollector{ pool: pool, acquiredConns: desc("acquired_conns", "Connections in use."), idleConns: desc("idle_conns", "Idle connections."), totalConns: desc("total_conns", "Open connections, in use, idle and being opened."), maxConns: desc("max_conns", "Most connections the pool opens."), acquires: desc("acquires_total", "Connections handed out."), acquireWait: desc("acquire_wait_seconds_total", "Total time spent waiting for a connection."), emptyAcquires: desc("empty_acquires_total", "Acquires that had to wait because no connection was idle."), canceledAcquires: desc("canceled_acquires_total", "Acquires canceled while waiting, for example by a timeout."), newConns: desc("new_conns_total", "Connections opened."), maxLifetimeDestroyed: desc("max_lifetime_destroyed_total", "Connections closed for reaching their maximum lifetime."), maxIdleDestroyed: desc("max_idle_destroyed_total", "Connections closed for being idle too long."), } } func (c *poolCollector) Describe(ch chan<- *prometheus.Desc) { prometheus.DescribeByCollect(c, ch) } func (c *poolCollector) Collect(ch chan<- prometheus.Metric) { s := c.pool.Stat() gauge := func(d *prometheus.Desc, v float64) { ch <- prometheus.MustNewConstMetric(d, prometheus.GaugeValue, v) } counter := func(d *prometheus.Desc, v float64) { ch <- prometheus.MustNewConstMetric(d, prometheus.CounterValue, v) } gauge(c.acquiredConns, float64(s.AcquiredConns())) gauge(c.idleConns, float64(s.IdleConns())) gauge(c.totalConns, float64(s.TotalConns())) gauge(c.maxConns, float64(s.MaxConns())) counter(c.acquires, float64(s.AcquireCount())) counter(c.acquireWait, s.AcquireDuration().Seconds()) counter(c.emptyAcquires, float64(s.EmptyAcquireCount())) counter(c.canceledAcquires, float64(s.CanceledAcquireCount())) counter(c.newConns, float64(s.NewConnsCount())) counter(c.maxLifetimeDestroyed, float64(s.MaxLifetimeDestroyCount())) counter(c.maxIdleDestroyed, float64(s.MaxIdleDestroyCount())) }