veza/veza-backend-api/internal/metrics/db_pool.go
2025-12-12 21:34:34 -05:00

121 lines
4.2 KiB
Go

package metrics
import (
"database/sql"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
// dbPoolOpenConnections mesure le nombre de connexions ouvertes dans le pool
dbPoolOpenConnections = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_open_connections",
Help: "Number of open database connections in the pool",
},
)
// dbPoolInUse mesure le nombre de connexions en cours d'utilisation
dbPoolInUse = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_in_use",
Help: "Number of database connections currently in use",
},
)
// dbPoolIdle mesure le nombre de connexions inactives
dbPoolIdle = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_idle",
Help: "Number of idle database connections in the pool",
},
)
// dbPoolWaitCount mesure le nombre total de fois qu'une connexion a dû attendre
// Note: sql.DBStats.WaitCount est cumulatif depuis le démarrage, donc on utilise un Gauge
// et on le met à jour avec la valeur absolue
dbPoolWaitCount = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_wait_count_total",
Help: "Total number of times a connection had to wait (cumulative since startup)",
},
)
// dbPoolWaitDuration mesure la durée totale d'attente pour obtenir une connexion
// Note: sql.DBStats.WaitDuration est cumulatif depuis le démarrage, donc on utilise un Gauge
dbPoolWaitDuration = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_wait_duration_seconds_total",
Help: "Total time spent waiting for a database connection in seconds (cumulative since startup)",
},
)
// dbPoolMaxIdleClosed mesure le nombre de connexions fermées à cause de MaxIdleConns
// Note: sql.DBStats.MaxIdleClosed est cumulatif depuis le démarrage, donc on utilise un Gauge
dbPoolMaxIdleClosed = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_max_idle_closed_total",
Help: "Total number of connections closed due to MaxIdleConns limit (cumulative since startup)",
},
)
// dbPoolMaxIdleTimeClosed mesure le nombre de connexions fermées à cause de MaxIdleTime
// Note: sql.DBStats.MaxIdleTimeClosed est cumulatif depuis le démarrage, donc on utilise un Gauge
dbPoolMaxIdleTimeClosed = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_max_idle_time_closed_total",
Help: "Total number of connections closed due to MaxIdleTime limit (cumulative since startup)",
},
)
// dbPoolMaxLifetimeClosed mesure le nombre de connexions fermées à cause de MaxLifetime
// Note: sql.DBStats.MaxLifetimeClosed est cumulatif depuis le démarrage, donc on utilise un Gauge
dbPoolMaxLifetimeClosed = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "veza_db_pool_max_lifetime_closed_total",
Help: "Total number of connections closed due to MaxLifetime limit (cumulative since startup)",
},
)
)
// UpdateDBPoolStats met à jour les métriques du pool de connexions DB
// MOD-P2-004: Expose les métriques database/sql stats via Prometheus
func UpdateDBPoolStats(stats sql.DBStats) {
// Métriques de connexions actuelles
dbPoolOpenConnections.Set(float64(stats.OpenConnections))
dbPoolInUse.Set(float64(stats.InUse))
dbPoolIdle.Set(float64(stats.Idle))
// Métriques de wait (cumulatives depuis le démarrage)
// Note: sql.DBStats fournit des valeurs cumulatives, donc on utilise Set pour mettre à jour les gauges
dbPoolWaitCount.Set(float64(stats.WaitCount))
dbPoolWaitDuration.Set(stats.WaitDuration.Seconds())
// Métriques de connexions fermées (cumulatives depuis le démarrage)
dbPoolMaxIdleClosed.Set(float64(stats.MaxIdleClosed))
dbPoolMaxIdleTimeClosed.Set(float64(stats.MaxIdleTimeClosed))
dbPoolMaxLifetimeClosed.Set(float64(stats.MaxLifetimeClosed))
}
// StartDBPoolStatsCollector démarre un collecteur périodique pour les métriques DB pool
// MOD-P2-004: Collecte les stats DB pool périodiquement et les expose via Prometheus
func StartDBPoolStatsCollector(db *sql.DB, interval time.Duration) {
if db == nil {
return
}
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
// Collecter immédiatement
UpdateDBPoolStats(db.Stats())
// Collecter périodiquement
for range ticker.C {
UpdateDBPoolStats(db.Stats())
}
}()
}