mirror of
https://github.com/nprasad2077/NBA_Go.git
synced 2026-09-22 14:05:13 +00:00
PG DB reroute
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
// Define metrics
|
||||
@@ -11,7 +15,7 @@ var (
|
||||
HTTPRequestsTotal = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "nba_http_requests_total",
|
||||
Help: "Total number of HTTP requests",
|
||||
Help: "Total number of HTTP requests processed",
|
||||
},
|
||||
[]string{"method", "endpoint", "status"},
|
||||
)
|
||||
@@ -20,18 +24,92 @@ var (
|
||||
HTTPRequestDuration = promauto.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "nba_http_request_duration_seconds",
|
||||
Help: "HTTP request duration in seconds",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
Help: "HTTP request latency in seconds",
|
||||
Buckets: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
|
||||
},
|
||||
[]string{"method", "endpoint"},
|
||||
)
|
||||
|
||||
// DBOperationsTotal counts database operations
|
||||
// DBOperationsTotal counts database operations (connect, migrate)
|
||||
DBOperationsTotal = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "nba_db_operations_total",
|
||||
Help: "Total number of database operations",
|
||||
Help: "Total number of database lifecycle operations",
|
||||
},
|
||||
[]string{"operation", "entity"},
|
||||
)
|
||||
)
|
||||
|
||||
// DBPoolOpenConns tracks current open connections per pool
|
||||
DBPoolOpenConns = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "nba_db_pool_open_connections",
|
||||
Help: "Current number of open connections in pool",
|
||||
},
|
||||
[]string{"pool"},
|
||||
)
|
||||
|
||||
// DBPoolInUseConns tracks connections currently executing queries
|
||||
DBPoolInUseConns = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "nba_db_pool_in_use_connections",
|
||||
Help: "Current number of in-use active connections executing queries",
|
||||
},
|
||||
[]string{"pool"},
|
||||
)
|
||||
|
||||
// DBPoolIdleConns tracks idle connections available in pool
|
||||
DBPoolIdleConns = promauto.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "nba_db_pool_idle_connections",
|
||||
Help: "Current number of idle connections in pool",
|
||||
},
|
||||
[]string{"pool"},
|
||||
)
|
||||
|
||||
// DBPoolWaitCount tracks connection wait occurrences
|
||||
DBPoolWaitCount = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "nba_db_pool_wait_count_total",
|
||||
Help: "Total number of connection waits due to pool saturation",
|
||||
},
|
||||
[]string{"pool"},
|
||||
)
|
||||
|
||||
// DBPoolWaitDuration tracks time spent waiting for a connection
|
||||
DBPoolWaitDuration = promauto.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "nba_db_pool_wait_duration_seconds_total",
|
||||
Help: "Total seconds blocked waiting for a connection",
|
||||
},
|
||||
[]string{"pool"},
|
||||
)
|
||||
)
|
||||
|
||||
// StartDBPoolMetricsCollector periodically collects sql.DBStats for both pools
|
||||
func StartDBPoolMetricsCollector(db *gorm.DB) {
|
||||
if db == nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
// Write Pool (Sources)
|
||||
if writeDB, err := db.Clauses(dbresolver.Write).DB(); err == nil && writeDB != nil {
|
||||
stats := writeDB.Stats()
|
||||
DBPoolOpenConns.WithLabelValues("write").Set(float64(stats.OpenConnections))
|
||||
DBPoolInUseConns.WithLabelValues("write").Set(float64(stats.InUse))
|
||||
DBPoolIdleConns.WithLabelValues("write").Set(float64(stats.Idle))
|
||||
}
|
||||
|
||||
// Read Pool (Replicas)
|
||||
if readDB, err := db.Clauses(dbresolver.Read).DB(); err == nil && readDB != nil {
|
||||
stats := readDB.Stats()
|
||||
DBPoolOpenConns.WithLabelValues("read").Set(float64(stats.OpenConnections))
|
||||
DBPoolInUseConns.WithLabelValues("read").Set(float64(stats.InUse))
|
||||
DBPoolIdleConns.WithLabelValues("read").Set(float64(stats.Idle))
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// StructuredLogger logs incoming HTTP requests using slog with X-Request-ID correlation.
|
||||
func StructuredLogger() fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
start := time.Now()
|
||||
reqID := c.Get("X-Request-ID")
|
||||
if reqID == "" {
|
||||
reqID = uuid.NewString()
|
||||
c.Set("X-Request-ID", reqID)
|
||||
}
|
||||
c.Locals("requestId", reqID)
|
||||
|
||||
err := c.Next()
|
||||
duration := time.Since(start)
|
||||
|
||||
slog.Info("HTTP Request",
|
||||
"request_id", reqID,
|
||||
"method", c.Method(),
|
||||
"path", c.Path(),
|
||||
"status", c.Response().StatusCode(),
|
||||
"duration_ms", duration.Milliseconds(),
|
||||
"ip", c.IP(),
|
||||
"user_agent", c.Get("User-Agent"),
|
||||
)
|
||||
return err
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user