File size: 4,716 Bytes
ca50bff | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | package internal
import (
"sync"
"sync/atomic"
"time"
)
// ModelStats 模型统计
type ModelStats struct {
Requests int64 `json:"requests"`
InputTok int64 `json:"input_tokens"`
OutputTok int64 `json:"output_tokens"`
}
// Telemetry 遥测数据
type Telemetry struct {
StartTime time.Time
TotalRequests int64
TotalInputTok int64
TotalOutputTok int64
minuteRequests int64
minuteInputTok int64
minuteOutputTok int64
requestTimes []time.Time
modelStats map[string]*ModelStats
mu sync.Mutex
}
var telemetry = &Telemetry{
StartTime: time.Now(),
requestTimes: make([]time.Time, 0),
modelStats: make(map[string]*ModelStats),
}
func RecordRequest(inputTokens, outputTokens int64, model string) {
atomic.AddInt64(&telemetry.TotalRequests, 1)
atomic.AddInt64(&telemetry.TotalInputTok, inputTokens)
atomic.AddInt64(&telemetry.TotalOutputTok, outputTokens)
atomic.AddInt64(&telemetry.minuteRequests, 1)
atomic.AddInt64(&telemetry.minuteInputTok, inputTokens)
atomic.AddInt64(&telemetry.minuteOutputTok, outputTokens)
telemetry.mu.Lock()
telemetry.requestTimes = append(telemetry.requestTimes, time.Now())
// 模型维度统计
if model != "" {
if _, ok := telemetry.modelStats[model]; !ok {
telemetry.modelStats[model] = &ModelStats{}
}
telemetry.modelStats[model].Requests++
telemetry.modelStats[model].InputTok += inputTokens
telemetry.modelStats[model].OutputTok += outputTokens
}
telemetry.mu.Unlock()
}
func GetRPM() int {
telemetry.mu.Lock()
defer telemetry.mu.Unlock()
now := time.Now()
cutoff := now.Add(-time.Minute)
validTimes := make([]time.Time, 0)
for _, t := range telemetry.requestTimes {
if t.After(cutoff) {
validTimes = append(validTimes, t)
}
}
telemetry.requestTimes = validTimes
return len(validTimes)
}
type TelemetryData struct {
Uptime string `json:"uptime"`
TotalRequests int64 `json:"total_requests"`
RPM int `json:"rpm"`
TotalInputTok int64 `json:"total_input_tokens"`
TotalOutputTok int64 `json:"total_output_tokens"`
AvgInputTok int64 `json:"avg_input_tokens"`
AvgOutputTok int64 `json:"avg_output_tokens"`
ValidTokens int `json:"valid_tokens"`
MultimodalCalls int64 `json:"multimodal_calls"`
TotalCalls int64 `json:"total_calls"`
SuccessCalls int64 `json:"success_calls"`
SuccessRate float64 `json:"success_rate"`
ModelStats map[string]*ModelStats `json:"model_stats,omitempty"`
}
func GetTelemetryData() TelemetryData {
totalReqs := atomic.LoadInt64(&telemetry.TotalRequests)
totalIn := atomic.LoadInt64(&telemetry.TotalInputTok)
totalOut := atomic.LoadInt64(&telemetry.TotalOutputTok)
var avgIn, avgOut int64
if totalReqs > 0 {
avgIn = totalIn / totalReqs
avgOut = totalOut / totalReqs
}
uptime := time.Since(telemetry.StartTime)
uptimeStr := formatDuration(uptime)
// 获取 token 管理器统计
tmStats := GetTokenManager().GetStats()
// 复制模型统计
telemetry.mu.Lock()
modelStatsCopy := make(map[string]*ModelStats)
for k, v := range telemetry.modelStats {
modelStatsCopy[k] = &ModelStats{
Requests: v.Requests,
InputTok: v.InputTok,
OutputTok: v.OutputTok,
}
}
telemetry.mu.Unlock()
return TelemetryData{
Uptime: uptimeStr,
TotalRequests: totalReqs,
RPM: GetRPM(),
TotalInputTok: totalIn,
TotalOutputTok: totalOut,
AvgInputTok: avgIn,
AvgOutputTok: avgOut,
ValidTokens: tmStats.ValidTokenCount,
MultimodalCalls: tmStats.MultimodalCount,
TotalCalls: tmStats.TotalCalls,
SuccessCalls: tmStats.SuccessCalls,
SuccessRate: tmStats.SuccessRate,
ModelStats: modelStatsCopy,
}
}
func formatDuration(d time.Duration) string {
days := int(d.Hours()) / 24
hours := int(d.Hours()) % 24
minutes := int(d.Minutes()) % 60
seconds := int(d.Seconds()) % 60
if days > 0 {
return formatTime(days, "d") + formatTime(hours, "h") + formatTime(minutes, "m")
}
if hours > 0 {
return formatTime(hours, "h") + formatTime(minutes, "m") + formatTime(seconds, "s")
}
if minutes > 0 {
return formatTime(minutes, "m") + formatTime(seconds, "s")
}
return formatTime(seconds, "s")
}
func formatTime(value int, unit string) string {
if value == 0 {
return ""
}
return string(rune('0'+value/10)) + string(rune('0'+value%10)) + unit
}
|