claw-code/.guardrails/mcp-server/internal/database/metrics.go

99 lines
2.1 KiB
Go

package database
import (
"context"
"log/slog"
"time"
"github.com/thearchitectit/guardrail-mcp/internal/metrics"
)
// MetricsCollector periodically collects and reports database metrics
type MetricsCollector struct {
db *DB
ticker *time.Ticker
stop chan struct{}
}
// NewMetricsCollector creates a new database metrics collector
func NewMetricsCollector(db *DB, interval time.Duration) *MetricsCollector {
return &MetricsCollector{
db: db,
ticker: time.NewTicker(interval),
stop: make(chan struct{}),
}
}
// Start begins collecting database metrics
func (c *MetricsCollector) Start() {
// Collect immediately
c.collect()
go func() {
for {
select {
case <-c.ticker.C:
c.collect()
case <-c.stop:
c.ticker.Stop()
return
}
}
}()
}
// Stop stops the metrics collector
func (c *MetricsCollector) Stop() {
close(c.stop)
}
// collect gathers and reports current database metrics
func (c *MetricsCollector) collect() {
stats := c.db.PoolStats()
metricStats := struct {
Open int
InUse int
Idle int
WaitDuration float64
WaitCount int64
}{
Open: stats.OpenConnections,
InUse: stats.InUse,
Idle: stats.Idle,
WaitDuration: stats.WaitDuration.Seconds(),
WaitCount: stats.WaitCount,
}
metrics.RecordDBStats(metricStats)
// Log warnings if pool is near capacity
if stats.OpenConnections > stats.MaxOpenConnections*90/100 {
slog.Warn("Database connection pool near capacity",
"open", stats.OpenConnections,
"max", stats.MaxOpenConnections,
"in_use", stats.InUse,
"idle", stats.Idle,
)
}
// Log if there are waits for connections
if stats.WaitCount > 0 {
slog.Debug("Database connection waits detected",
"wait_count", stats.WaitCount,
"wait_duration_sec", stats.WaitDuration.Seconds(),
)
}
}
// TimedQuery executes a database query and records metrics
func (db *DB) TimedQuery(ctx context.Context, operation, table string, queryFunc func() error) error {
start := time.Now()
err := queryFunc()
duration := time.Since(start)
metrics.RecordDBQuery(operation, table, duration)
return err
}