Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

119 строки
3.8 KiB

  1. package metrics
  2. import (
  3. "net/http"
  4. "os"
  5. "sync"
  6. "github.com/prometheus/client_golang/prometheus"
  7. "github.com/prometheus/client_golang/prometheus/promhttp"
  8. )
  9. var (
  10. globalMetrics *Metrics
  11. globalOnce sync.Once
  12. )
  13. // Metrics 包含所有 Prometheus 指标
  14. type Metrics struct {
  15. RequestsTotal *prometheus.CounterVec
  16. RequestErrorsTotal *prometheus.CounterVec
  17. RequestRetriesTotal *prometheus.CounterVec
  18. TokensTotal *prometheus.CounterVec
  19. QuotaConsumedTotal *prometheus.CounterVec
  20. RequestDuration *prometheus.HistogramVec
  21. UpstreamDuration *prometheus.HistogramVec
  22. FirstTokenDuration *prometheus.HistogramVec
  23. ActiveRequests *prometheus.GaugeVec
  24. }
  25. // NewMetrics 创建并注册所有指标到给定 Registry
  26. func NewMetrics(reg prometheus.Registerer) *Metrics {
  27. m := &Metrics{
  28. RequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
  29. Name: "newapi_requests_total",
  30. Help: "Total number of API requests",
  31. }, []string{"channel", "model", "code", "is_stream", "relay_mode"}),
  32. RequestErrorsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
  33. Name: "newapi_request_errors_total",
  34. Help: "Total number of request errors",
  35. }, []string{"channel", "model", "error_type", "error_code"}),
  36. RequestRetriesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
  37. Name: "newapi_request_retries_total",
  38. Help: "Total number of request retries",
  39. }, []string{"channel", "model"}),
  40. TokensTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
  41. Name: "newapi_tokens_total",
  42. Help: "Total tokens used",
  43. }, []string{"channel", "model", "type"}),
  44. QuotaConsumedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{
  45. Name: "newapi_quota_consumed_total",
  46. Help: "Total quota consumed",
  47. }, []string{"channel", "model", "billing_source"}),
  48. RequestDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
  49. Name: "newapi_request_duration_seconds",
  50. Help: "End-to-end request duration in seconds",
  51. Buckets: []float64{0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120},
  52. }, []string{"channel", "model", "is_stream", "relay_mode"}),
  53. UpstreamDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
  54. Name: "newapi_upstream_duration_seconds",
  55. Help: "Upstream response duration in seconds",
  56. Buckets: []float64{0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120},
  57. }, []string{"channel", "model"}),
  58. FirstTokenDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
  59. Name: "newapi_first_token_duration_seconds",
  60. Help: "Time to first token in seconds (streaming only)",
  61. Buckets: []float64{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
  62. }, []string{"channel", "model"}),
  63. ActiveRequests: prometheus.NewGaugeVec(prometheus.GaugeOpts{
  64. Name: "newapi_active_requests",
  65. Help: "Current number of active requests",
  66. }, []string{"model"}),
  67. }
  68. reg.MustRegister(
  69. m.RequestsTotal,
  70. m.RequestErrorsTotal,
  71. m.RequestRetriesTotal,
  72. m.TokensTotal,
  73. m.QuotaConsumedTotal,
  74. m.RequestDuration,
  75. m.UpstreamDuration,
  76. m.FirstTokenDuration,
  77. m.ActiveRequests,
  78. )
  79. return m
  80. }
  81. // GetMetrics 返回全局 Metrics 实例
  82. func GetMetrics() *Metrics {
  83. globalOnce.Do(func() {
  84. if os.Getenv("METRICS_ENABLED") == "false" {
  85. globalMetrics = NewMetrics(prometheus.NewPedanticRegistry())
  86. return
  87. }
  88. globalMetrics = NewMetrics(prometheus.DefaultRegisterer)
  89. })
  90. return globalMetrics
  91. }
  92. // IsEnabled 返回 metrics 是否启用
  93. func IsEnabled() bool {
  94. return os.Getenv("METRICS_ENABLED") != "false"
  95. }
  96. // NewMetricsHandler 返回默认 registry 的 /metrics HTTP handler
  97. func NewMetricsHandler() http.Handler {
  98. return promhttp.Handler()
  99. }
  100. // NewMetricsHandlerWithRegistry 返回指定 registry 的 /metrics HTTP handler
  101. func NewMetricsHandlerWithRegistry(reg *prometheus.Registry) http.Handler {
  102. return promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
  103. }