|
- package metrics
-
- import (
- "net/http"
- "os"
- "sync"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/promhttp"
- )
-
- var (
- globalMetrics *Metrics
- globalOnce sync.Once
- )
-
- // Metrics 包含所有 Prometheus 指标
- type Metrics struct {
- RequestsTotal *prometheus.CounterVec
- RequestErrorsTotal *prometheus.CounterVec
- RequestRetriesTotal *prometheus.CounterVec
- TokensTotal *prometheus.CounterVec
- QuotaConsumedTotal *prometheus.CounterVec
-
- RequestDuration *prometheus.HistogramVec
- UpstreamDuration *prometheus.HistogramVec
- FirstTokenDuration *prometheus.HistogramVec
-
- ActiveRequests *prometheus.GaugeVec
- }
-
- // NewMetrics 创建并注册所有指标到给定 Registry
- func NewMetrics(reg prometheus.Registerer) *Metrics {
- m := &Metrics{
- RequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "newapi_requests_total",
- Help: "Total number of API requests",
- }, []string{"channel", "model", "code", "is_stream", "relay_mode"}),
- RequestErrorsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "newapi_request_errors_total",
- Help: "Total number of request errors",
- }, []string{"channel", "model", "error_type", "error_code"}),
- RequestRetriesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "newapi_request_retries_total",
- Help: "Total number of request retries",
- }, []string{"channel", "model"}),
- TokensTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "newapi_tokens_total",
- Help: "Total tokens used",
- }, []string{"channel", "model", "type"}),
- QuotaConsumedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
- Name: "newapi_quota_consumed_total",
- Help: "Total quota consumed",
- }, []string{"channel", "model", "billing_source"}),
-
- RequestDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Name: "newapi_request_duration_seconds",
- Help: "End-to-end request duration in seconds",
- Buckets: []float64{0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120},
- }, []string{"channel", "model", "is_stream", "relay_mode"}),
- UpstreamDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Name: "newapi_upstream_duration_seconds",
- Help: "Upstream response duration in seconds",
- Buckets: []float64{0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120},
- }, []string{"channel", "model"}),
- FirstTokenDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
- Name: "newapi_first_token_duration_seconds",
- Help: "Time to first token in seconds (streaming only)",
- Buckets: []float64{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
- }, []string{"channel", "model"}),
-
- ActiveRequests: prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Name: "newapi_active_requests",
- Help: "Current number of active requests",
- }, []string{"model"}),
- }
-
- reg.MustRegister(
- m.RequestsTotal,
- m.RequestErrorsTotal,
- m.RequestRetriesTotal,
- m.TokensTotal,
- m.QuotaConsumedTotal,
- m.RequestDuration,
- m.UpstreamDuration,
- m.FirstTokenDuration,
- m.ActiveRequests,
- )
-
- return m
- }
-
- // GetMetrics 返回全局 Metrics 实例
- func GetMetrics() *Metrics {
- globalOnce.Do(func() {
- if os.Getenv("METRICS_ENABLED") == "false" {
- globalMetrics = NewMetrics(prometheus.NewPedanticRegistry())
- return
- }
- globalMetrics = NewMetrics(prometheus.DefaultRegisterer)
- })
- return globalMetrics
- }
-
- // IsEnabled 返回 metrics 是否启用
- func IsEnabled() bool {
- return os.Getenv("METRICS_ENABLED") != "false"
- }
-
- // NewMetricsHandler 返回默认 registry 的 /metrics HTTP handler
- func NewMetricsHandler() http.Handler {
- return promhttp.Handler()
- }
-
- // NewMetricsHandlerWithRegistry 返回指定 registry 的 /metrics HTTP handler
- func NewMetricsHandlerWithRegistry(reg *prometheus.Registry) http.Handler {
- return promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
- }
|