Skip to content

Commit

Permalink
Add pool_name label to the gauges
Browse files Browse the repository at this point in the history
This is kinda handy when you have more than 1 DB connection pool - for
example, when connecting to a cluster of N shards.
  • Loading branch information
tony2001 authored and hypnoglow committed Jul 13, 2023
1 parent 17e25ee commit 00ab652
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 18 deletions.
6 changes: 6 additions & 0 deletions example/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"os"

"github.com/go-pg/pg/v9"
Expand All @@ -17,6 +18,9 @@ func main() {

db := pg.Connect(dbOpts)

// create unique pool name from DB address and database name
poolName := fmt.Printf("%s/%s", dbOpts.Addr, dbOpts.Database)

mon := monitor.NewMonitor(
// Observer package must match your go-pg version.
// E.g. for go-pg v10.x.x use package gopgv10.
Expand All @@ -31,6 +35,8 @@ func main() {
// my_app_go_pg_pool_hits{}
monitor.MetricsWithNamespace("my_app"),
),
// set pool name
monitor.MonitorWithPoolName(poolName),
)

mon.Open()
Expand Down
30 changes: 18 additions & 12 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ type Metrics struct {

constLabels prometheus.Labels

hits prometheus.Gauge
misses prometheus.Gauge
timeouts prometheus.Gauge
hits *prometheus.GaugeVec
misses *prometheus.GaugeVec
timeouts *prometheus.GaugeVec

totalConns prometheus.Gauge
idleConns prometheus.Gauge
staleConns prometheus.Gauge
totalConns *prometheus.GaugeVec
idleConns *prometheus.GaugeVec
staleConns *prometheus.GaugeVec

registerer prometheus.Registerer
}
Expand Down Expand Up @@ -71,74 +71,80 @@ func NewMetrics(opts ...MetricsOption) *Metrics {
opt(m)
}

hits := prometheus.NewGauge(
hits := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_hits",
Help: "Number of times free connection was found in the pool",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(hits)
m.hits = hits

misses := prometheus.NewGauge(
misses := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_misses",
Help: "Number of times free connection was NOT found in the pool",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(misses)
m.misses = misses

timeouts := prometheus.NewGauge(
timeouts := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_timeouts",
Help: "Number of times a wait timeout occurred",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(timeouts)
m.timeouts = timeouts

totalConns := prometheus.NewGauge(
totalConns := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_total_connections",
Help: "Number of total connections in the pool",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(totalConns)
m.totalConns = totalConns

idleConns := prometheus.NewGauge(
idleConns := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_idle_connections",
Help: "Number of idle connections in the pool",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(idleConns)
m.idleConns = idleConns

staleConns := prometheus.NewGauge(
staleConns := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: m.namespace,
Subsystem: m.subsystem,
ConstLabels: m.constLabels,
Name: "pool_stale_connections",
Help: "Number of stale connections removed from the pool",
},
[]string{"pool_name"},
)
m.registerer.MustRegister(staleConns)
m.staleConns = staleConns
Expand Down
21 changes: 15 additions & 6 deletions monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ type Monitor struct {
wg sync.WaitGroup
ctx context.Context
cancel context.CancelFunc

poolName string
}

// MonitorOption is an option for NewMonitor.
type MonitorOption func(monitor *Monitor)

// MonitorWithPoolName is an option that sets pool name for the monitor.
func MonitorWithPoolName(poolName string) MonitorOption { //nolint:golint
return func(monitor *Monitor) {
monitor.poolName = poolName
}
}

// NewMonitor returns a new configured Monitor.
func NewMonitor(observer Observer, metrics *Metrics, opts ...MonitorOption) *Monitor {
m := &Monitor{
Expand Down Expand Up @@ -79,11 +88,11 @@ func (m *Monitor) worker() {
func (m *Monitor) sync() {
stats := m.observer.Observe()

m.metrics.hits.Set(float64(stats.Hits))
m.metrics.misses.Set(float64(stats.Misses))
m.metrics.timeouts.Set(float64(stats.Timeouts))
m.metrics.hits.WithLabelValues(m.poolName).Set(float64(stats.Hits))
m.metrics.misses.WithLabelValues(m.poolName).Set(float64(stats.Misses))
m.metrics.timeouts.WithLabelValues(m.poolName).Set(float64(stats.Timeouts))

m.metrics.totalConns.Set(float64(stats.TotalConns))
m.metrics.idleConns.Set(float64(stats.IdleConns))
m.metrics.staleConns.Set(float64(stats.StaleConns))
m.metrics.totalConns.WithLabelValues(m.poolName).Set(float64(stats.TotalConns))
m.metrics.idleConns.WithLabelValues(m.poolName).Set(float64(stats.IdleConns))
m.metrics.staleConns.WithLabelValues(m.poolName).Set(float64(stats.StaleConns))
}

0 comments on commit 00ab652

Please sign in to comment.