more features
This commit is contained in:
@@ -60,6 +60,8 @@ type StatsCollector struct {
|
|||||||
requestStats []ResponseStats
|
requestStats []ResponseStats
|
||||||
methodStats map[string][]time.Duration // Track durations by method
|
methodStats map[string][]time.Duration // Track durations by method
|
||||||
backendMethodStats map[string]map[string][]time.Duration // Track durations by backend and method
|
backendMethodStats map[string]map[string][]time.Duration // Track durations by backend and method
|
||||||
|
backendWins map[string]int // Track how many times each backend responded first
|
||||||
|
methodBackendWins map[string]map[string]int // Track wins per method per backend
|
||||||
totalRequests int
|
totalRequests int
|
||||||
errorCount int
|
errorCount int
|
||||||
wsConnections []WebSocketStats // Track websocket connections
|
wsConnections []WebSocketStats // Track websocket connections
|
||||||
@@ -79,6 +81,8 @@ func NewStatsCollector(summaryInterval time.Duration) *StatsCollector {
|
|||||||
requestStats: make([]ResponseStats, 0, 1000),
|
requestStats: make([]ResponseStats, 0, 1000),
|
||||||
methodStats: make(map[string][]time.Duration),
|
methodStats: make(map[string][]time.Duration),
|
||||||
backendMethodStats: make(map[string]map[string][]time.Duration),
|
backendMethodStats: make(map[string]map[string][]time.Duration),
|
||||||
|
backendWins: make(map[string]int),
|
||||||
|
methodBackendWins: make(map[string]map[string]int),
|
||||||
appStartTime: now,
|
appStartTime: now,
|
||||||
intervalStartTime: now,
|
intervalStartTime: now,
|
||||||
summaryInterval: summaryInterval,
|
summaryInterval: summaryInterval,
|
||||||
@@ -174,6 +178,30 @@ func (sc *StatsCollector) AddStats(stats []ResponseStats, totalDuration time.Dur
|
|||||||
sc.mu.Lock()
|
sc.mu.Lock()
|
||||||
defer sc.mu.Unlock()
|
defer sc.mu.Unlock()
|
||||||
|
|
||||||
|
// Find the fastest successful response
|
||||||
|
var fastestBackend string
|
||||||
|
var fastestDuration time.Duration = time.Hour // Initialize with a very large duration
|
||||||
|
var method string
|
||||||
|
|
||||||
|
for _, stat := range stats {
|
||||||
|
if stat.Error == nil && stat.Duration < fastestDuration {
|
||||||
|
fastestDuration = stat.Duration
|
||||||
|
fastestBackend = stat.Backend
|
||||||
|
method = stat.Method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track the win if we found a successful response
|
||||||
|
if fastestBackend != "" {
|
||||||
|
sc.backendWins[fastestBackend]++
|
||||||
|
|
||||||
|
// Track wins per method
|
||||||
|
if _, exists := sc.methodBackendWins[method]; !exists {
|
||||||
|
sc.methodBackendWins[method] = make(map[string]int)
|
||||||
|
}
|
||||||
|
sc.methodBackendWins[method][fastestBackend]++
|
||||||
|
}
|
||||||
|
|
||||||
// Add stats to the collection
|
// Add stats to the collection
|
||||||
for _, stat := range stats {
|
for _, stat := range stats {
|
||||||
sc.requestStats = append(sc.requestStats, stat)
|
sc.requestStats = append(sc.requestStats, stat)
|
||||||
@@ -446,6 +474,34 @@ func (sc *StatsCollector) printSummary() {
|
|||||||
formatDuration(p50), formatDuration(p90), formatDuration(p99))
|
formatDuration(p50), formatDuration(p90), formatDuration(p99))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print backend wins statistics
|
||||||
|
fmt.Printf("\nBackend First Response Wins:\n")
|
||||||
|
fmt.Printf("%-20s %10s %10s\n", "Backend", "Wins", "Win %")
|
||||||
|
fmt.Printf("%s\n", strings.Repeat("-", 42))
|
||||||
|
|
||||||
|
totalWins := 0
|
||||||
|
for _, wins := range sc.backendWins {
|
||||||
|
totalWins += wins
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort backends by wins for consistent output
|
||||||
|
type backendWin struct {
|
||||||
|
backend string
|
||||||
|
wins int
|
||||||
|
}
|
||||||
|
var winList []backendWin
|
||||||
|
for backend, wins := range sc.backendWins {
|
||||||
|
winList = append(winList, backendWin{backend, wins})
|
||||||
|
}
|
||||||
|
sort.Slice(winList, func(i, j int) bool {
|
||||||
|
return winList[i].wins > winList[j].wins
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, bw := range winList {
|
||||||
|
winPercentage := float64(bw.wins) / float64(totalWins) * 100
|
||||||
|
fmt.Printf("%-20s %10d %9.1f%%\n", bw.backend, bw.wins, winPercentage)
|
||||||
|
}
|
||||||
|
|
||||||
// Print per-method statistics
|
// Print per-method statistics
|
||||||
if len(sc.methodStats) > 0 {
|
if len(sc.methodStats) > 0 {
|
||||||
fmt.Printf("\nPer-Method Statistics (Primary Backend):\n")
|
fmt.Printf("\nPer-Method Statistics (Primary Backend):\n")
|
||||||
@@ -539,6 +595,35 @@ func (sc *StatsCollector) printSummary() {
|
|||||||
method := methodList[i].method
|
method := methodList[i].method
|
||||||
|
|
||||||
fmt.Printf("\n Method: %s (Total requests: %d)\n", method, methodList[i].count)
|
fmt.Printf("\n Method: %s (Total requests: %d)\n", method, methodList[i].count)
|
||||||
|
|
||||||
|
// Show wins for this method if available
|
||||||
|
if methodWins, exists := sc.methodBackendWins[method]; exists {
|
||||||
|
fmt.Printf(" First Response Wins: ")
|
||||||
|
totalMethodWins := 0
|
||||||
|
for _, wins := range methodWins {
|
||||||
|
totalMethodWins += wins
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort backends by wins for this method
|
||||||
|
var methodWinList []backendWin
|
||||||
|
for backend, wins := range methodWins {
|
||||||
|
methodWinList = append(methodWinList, backendWin{backend, wins})
|
||||||
|
}
|
||||||
|
sort.Slice(methodWinList, func(i, j int) bool {
|
||||||
|
return methodWinList[i].wins > methodWinList[j].wins
|
||||||
|
})
|
||||||
|
|
||||||
|
// Print wins inline
|
||||||
|
for idx, bw := range methodWinList {
|
||||||
|
if idx > 0 {
|
||||||
|
fmt.Printf(", ")
|
||||||
|
}
|
||||||
|
winPercentage := float64(bw.wins) / float64(totalMethodWins) * 100
|
||||||
|
fmt.Printf("%s: %d (%.1f%%)", bw.backend, bw.wins, winPercentage)
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Printf(" %-20s %10s %10s %10s %10s %10s %10s %10s\n",
|
fmt.Printf(" %-20s %10s %10s %10s %10s %10s %10s %10s\n",
|
||||||
"Backend", "Count", "Min", "Avg", "Max", "p50", "p90", "p99")
|
"Backend", "Count", "Min", "Avg", "Max", "p50", "p90", "p99")
|
||||||
fmt.Printf(" %s\n", strings.Repeat("-", 98))
|
fmt.Printf(" %s\n", strings.Repeat("-", 98))
|
||||||
@@ -625,6 +710,10 @@ func (sc *StatsCollector) printSummary() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset backend wins statistics
|
||||||
|
sc.backendWins = make(map[string]int)
|
||||||
|
sc.methodBackendWins = make(map[string]map[string]int)
|
||||||
|
|
||||||
// Reset CU counters for the next interval
|
// Reset CU counters for the next interval
|
||||||
sc.totalCU = 0
|
sc.totalCU = 0
|
||||||
sc.methodCU = make(map[string]int)
|
sc.methodCU = make(map[string]int)
|
||||||
|
|||||||
Reference in New Issue
Block a user