You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.3 KiB
Go

// Package metrics provides Prometheus metrics for the KnowFoolery application.
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
// Config holds the configuration for metrics.
type Config struct {
ServiceName string
Enabled bool
Registry prometheus.Registerer
}
// DefaultConfig returns a default configuration.
func DefaultConfig() Config {
return Config{
ServiceName: "knowfoolery",
Enabled: true,
}
}
// Metrics holds all Prometheus metrics for the application.
type Metrics struct {
config Config
// HTTP metrics
HTTPRequestsTotal *prometheus.CounterVec
HTTPRequestDuration *prometheus.HistogramVec
// Database metrics
DBConnectionsActive *prometheus.GaugeVec
DBQueryDuration *prometheus.HistogramVec
DBErrors *prometheus.CounterVec
// Cache metrics
CacheOperations *prometheus.CounterVec
CacheKeyCount *prometheus.GaugeVec
// Authentication metrics
AuthAttempts *prometheus.CounterVec
TokenOperations *prometheus.CounterVec
// Game metrics
GamesStarted *prometheus.CounterVec
GamesCompleted *prometheus.CounterVec
SessionDuration *prometheus.HistogramVec
QuestionsAsked *prometheus.CounterVec
AnswersSubmitted *prometheus.CounterVec
HintsRequested *prometheus.CounterVec
ScoreDistribution *prometheus.HistogramVec
}
// NewMetrics creates a new Metrics instance with all metrics registered.
func NewMetrics(config Config) *Metrics {
registry := config.Registry
if registry == nil {
registry = prometheus.DefaultRegisterer
}
auto := promauto.With(registry)
m := &Metrics{config: config}
// HTTP metrics
m.HTTPRequestsTotal = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"method", "endpoint", "status_code", "service"},
)
m.HTTPRequestDuration = auto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "HTTP request duration",
Buckets: prometheus.DefBuckets,
},
[]string{"method", "endpoint", "service"},
)
// Database metrics
m.DBConnectionsActive = auto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "db_connections_active",
Help: "Number of active database connections",
},
[]string{"database", "service"},
)
m.DBQueryDuration = auto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "db_query_duration_seconds",
Help: "Database query duration",
Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0},
},
[]string{"query_type", "table", "service"},
)
m.DBErrors = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "db_errors_total",
Help: "Total number of database errors",
},
[]string{"error_type", "service"},
)
// Cache metrics
m.CacheOperations = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "cache_operations_total",
Help: "Total number of cache operations",
},
[]string{"operation", "result", "service"},
)
m.CacheKeyCount = auto.NewGaugeVec(
prometheus.GaugeOpts{
Name: "cache_keys_total",
Help: "Number of keys in cache",
},
[]string{"cache_type", "service"},
)
// Authentication metrics
m.AuthAttempts = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "authentication_attempts_total",
Help: "Total authentication attempts",
},
[]string{"method", "result", "user_type"},
)
m.TokenOperations = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "token_operations_total",
Help: "JWT token operations",
},
[]string{"operation", "result"},
)
// Game metrics
m.GamesStarted = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "games_started_total",
Help: "Total number of games started",
},
[]string{"player_type", "platform"},
)
m.GamesCompleted = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "games_completed_total",
Help: "Total number of games completed",
},
[]string{"completion_type", "platform"},
)
m.SessionDuration = auto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "game_session_duration_seconds",
Help: "Duration of game sessions",
Buckets: []float64{60, 300, 600, 900, 1200, 1500, 1800},
},
[]string{"completion_type"},
)
m.QuestionsAsked = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "questions_asked_total",
Help: "Total number of questions asked",
},
[]string{"theme", "difficulty"},
)
m.AnswersSubmitted = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "answers_submitted_total",
Help: "Total number of answers submitted",
},
[]string{"theme", "is_correct", "attempt_number", "used_hint"},
)
m.HintsRequested = auto.NewCounterVec(
prometheus.CounterOpts{
Name: "hints_requested_total",
Help: "Total number of hints requested",
},
[]string{"theme", "question_difficulty"},
)
m.ScoreDistribution = auto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "game_scores",
Help: "Distribution of game scores",
Buckets: []float64{0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 80, 100},
},
[]string{"session_duration_bucket"},
)
return m
}
// ConfigFromEnv creates a Config from environment variables.
func ConfigFromEnv() Config {
// TODO: Implement environment variable parsing
return DefaultConfig()
}