// Package metrics Prometheus 指标:进程内 registry + 文本端点(api 层按开关挂载 /metrics)。 // // label 基数约束:channel/model 来自受管目录、status/kind 为有限枚举,可安全做 label; // 请求级随机值(trace id、用户 id、错误详情)禁止入 label,否则基数爆炸拖垮采集端。 package metrics import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" ) var reg = prometheus.NewRegistry() var ( // RequestsTotal 代理请求终结计数。channel 为 "none" 表示未打到任何渠道 // (无候选/满载等),model 为请求的模型名。 RequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "openteam_proxy_requests_total", Help: "Proxied requests terminated, by channel/model/status.", }, []string{"channel", "model", "status"}) // RequestDuration 请求从进入 handler 到终结的耗时(按渠道)。 RequestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: "openteam_proxy_request_duration_seconds", Help: "Proxy request duration, by channel.", Buckets: []float64{.05, .1, .25, .5, 1, 2.5, 5, 10, 30, 60, 120, 300}, }, []string{"channel"}) // ChannelFailures 上游失败计数(按渠道与失败类型),与运行期冷却同源。 ChannelFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "openteam_channel_failures_total", Help: "Upstream failures, by channel/fail kind.", }, []string{"channel", "kind"}) // RecorderQueueDepth 记账队列中待落库的记录数。持续增长说明 DB 写入跟不上。 RecorderQueueDepth = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "openteam_usage_queue_depth", Help: "Usage records buffered, waiting to be flushed.", }) // FrozenBalance 在途请求预扣(冻结)的金额合计(USD)。见 proxy 的 reserve/capture。 FrozenBalance = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "openteam_frozen_balance", Help: "Balance reserved by in-flight requests (USD).", }) ) func init() { reg.MustRegister( RequestsTotal, RequestDuration, ChannelFailures, RecorderQueueDepth, FrozenBalance, collectors.NewGoCollector(), collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}), ) } // Handler /metrics 的 http.Handler(独立 registry,避免全局默认注册器的耦合)。 func Handler() http.Handler { return promhttp.HandlerFor(reg, promhttp.HandlerOpts{}) }