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()) } }() }