2026-05-23 20:32:12 +08:00
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"runtime"
|
2026-06-26 19:12:50 +08:00
|
|
|
"strings"
|
2026-05-23 20:32:12 +08:00
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/volcano-tts/tts-api/common"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Stats struct {
|
2026-06-26 19:12:50 +08:00
|
|
|
totalRequests int64
|
|
|
|
|
successfulRequests int64
|
|
|
|
|
failedRequests int64
|
|
|
|
|
totalResponseTime time.Duration
|
|
|
|
|
recentResponseTimes []float64
|
|
|
|
|
responseTimesIndex int
|
|
|
|
|
responseTimesCount int
|
|
|
|
|
lastErrors []string
|
|
|
|
|
errorsIndex int
|
|
|
|
|
errorsCount int
|
|
|
|
|
mutex sync.RWMutex
|
2026-05-23 20:32:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var GlobalStats *Stats
|
|
|
|
|
|
|
|
|
|
func InitStats() {
|
|
|
|
|
GlobalStats = &Stats{
|
|
|
|
|
recentResponseTimes: make([]float64, common.MaxResponseTimes),
|
|
|
|
|
lastErrors: make([]string, common.MaxErrors),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Stats) AddRequest(success bool, responseTime time.Duration, errMsg string) {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
s.totalRequests++
|
|
|
|
|
s.totalResponseTime += responseTime
|
|
|
|
|
|
|
|
|
|
s.recentResponseTimes[s.responseTimesIndex] = responseTime.Seconds() * 1000
|
|
|
|
|
s.responseTimesIndex = (s.responseTimesIndex + 1) % common.MaxResponseTimes
|
2026-06-26 19:12:50 +08:00
|
|
|
if s.responseTimesCount < common.MaxResponseTimes {
|
|
|
|
|
s.responseTimesCount++
|
|
|
|
|
}
|
2026-05-23 20:32:12 +08:00
|
|
|
|
|
|
|
|
if success {
|
|
|
|
|
s.successfulRequests++
|
|
|
|
|
} else {
|
|
|
|
|
s.failedRequests++
|
|
|
|
|
if errMsg != "" {
|
2026-06-26 19:12:50 +08:00
|
|
|
now := time.Now().Format(time.RFC3339)
|
|
|
|
|
|
|
|
|
|
// 去重:如果最近一条错误的消息内容相同,仅更新时间戳
|
|
|
|
|
if s.errorsCount > 0 {
|
|
|
|
|
lastIdx := (s.errorsIndex - 1 + common.MaxErrors) % common.MaxErrors
|
|
|
|
|
lastEntry := s.lastErrors[lastIdx]
|
|
|
|
|
if sepIdx := strings.Index(lastEntry, ": "); sepIdx != -1 {
|
|
|
|
|
if lastEntry[sepIdx+2:] == errMsg {
|
|
|
|
|
s.lastErrors[lastIdx] = now + ": " + errMsg
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.lastErrors[s.errorsIndex] = now + ": " + errMsg
|
2026-05-23 20:32:12 +08:00
|
|
|
s.errorsIndex = (s.errorsIndex + 1) % common.MaxErrors
|
2026-06-26 19:12:50 +08:00
|
|
|
if s.errorsCount < common.MaxErrors {
|
|
|
|
|
s.errorsCount++
|
|
|
|
|
}
|
2026-05-23 20:32:12 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Stats) GetSnapshot() (totalRequests int64, successfulRequests int64, failedRequests int64,
|
|
|
|
|
totalResponseTime time.Duration, recentResponseTimes []float64, lastErrors []string) {
|
|
|
|
|
s.mutex.RLock()
|
|
|
|
|
defer s.mutex.RUnlock()
|
|
|
|
|
|
|
|
|
|
totalRequests = s.totalRequests
|
|
|
|
|
successfulRequests = s.successfulRequests
|
|
|
|
|
failedRequests = s.failedRequests
|
|
|
|
|
totalResponseTime = s.totalResponseTime
|
|
|
|
|
|
2026-06-26 19:12:50 +08:00
|
|
|
// 按时间顺序(从旧到新)遍历响应时间环形缓冲区
|
|
|
|
|
recentResponseTimes = make([]float64, 0, s.responseTimesCount)
|
|
|
|
|
if s.responseTimesCount > 0 {
|
|
|
|
|
start := 0
|
|
|
|
|
if s.responseTimesCount == common.MaxResponseTimes {
|
|
|
|
|
start = s.responseTimesIndex
|
|
|
|
|
}
|
|
|
|
|
for i := 0; i < s.responseTimesCount; i++ {
|
|
|
|
|
idx := (start + i) % common.MaxResponseTimes
|
|
|
|
|
recentResponseTimes = append(recentResponseTimes, s.recentResponseTimes[idx])
|
2026-05-23 20:32:12 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 19:12:50 +08:00
|
|
|
// 按时间顺序(从旧到新)遍历错误环形缓冲区
|
|
|
|
|
lastErrors = make([]string, 0, s.errorsCount)
|
|
|
|
|
if s.errorsCount > 0 {
|
|
|
|
|
start := 0
|
|
|
|
|
if s.errorsCount == common.MaxErrors {
|
|
|
|
|
start = s.errorsIndex
|
|
|
|
|
}
|
|
|
|
|
for i := 0; i < s.errorsCount; i++ {
|
|
|
|
|
idx := (start + i) % common.MaxErrors
|
|
|
|
|
lastErrors = append(lastErrors, s.lastErrors[idx])
|
2026-05-23 20:32:12 +08:00
|
|
|
}
|
|
|
|
|
}
|
2026-06-26 19:12:50 +08:00
|
|
|
|
2026-05-23 20:32:12 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetMemoryInfo() map[string]interface{} {
|
|
|
|
|
var m runtime.MemStats
|
|
|
|
|
runtime.ReadMemStats(&m)
|
|
|
|
|
return map[string]interface{}{
|
|
|
|
|
"total_alloc": m.TotalAlloc,
|
|
|
|
|
"heap_alloc": m.HeapAlloc,
|
|
|
|
|
"heap_inuse": m.HeapInuse,
|
|
|
|
|
"goroutines": runtime.NumGoroutine(),
|
|
|
|
|
}
|
|
|
|
|
}
|