Record delay test history in proxy info (Clash API standard compliance)

This commit is contained in:
NeoMody
2026-04-06 01:54:46 +08:00
parent 5e75f07aef
commit 2820313aea
2 changed files with 45 additions and 3 deletions

8
api.go
View File

@@ -86,7 +86,7 @@ func (b *Box) buildProxyInfo(tag, outType string, group proxyGroup) map[string]a
"type": capitalizeType(outType),
"alive": true,
"udp": true,
"history": []map[string]any{},
"history": b.getHistory(tag),
}
if group != nil {
info["now"] = group.Now()
@@ -394,13 +394,15 @@ func (b *Box) handleProxyDelay(w http.ResponseWriter, r *http.Request, name stri
delay, err := testProxyDelay(out, testURL, time.Duration(timeoutMs)*time.Millisecond)
if err != nil {
b.recordDelay(name, 0)
writeJSON(w, map[string]any{
"name": name,
"delay": 0,
"name": name,
"delay": 0,
"message": err.Error(),
})
return
}
b.recordDelay(name, delay)
writeJSON(w, map[string]any{
"name": name,
"delay": delay,

40
box.go
View File

@@ -5,6 +5,7 @@ import (
"fmt"
"net"
"strings"
"sync"
"time"
minidns "github.com/netkits-dev/mini-dns"
@@ -24,6 +25,12 @@ import (
N "github.com/sagernet/sing/common/network"
)
// DelayEntry records a single delay test result.
type DelayEntry struct {
Time time.Time `json:"time"`
Delay int `json:"delay"`
}
type Box struct {
createdAt time.Time
logFactory log.Factory
@@ -37,6 +44,39 @@ type Box struct {
apiLn net.Listener
clashMode string
modeList []string
delayHistory map[string][]DelayEntry // outbound tag -> recent delay results
delayHistoryMu sync.RWMutex
}
const maxDelayHistory = 10
func (b *Box) recordDelay(tag string, delay int) {
b.delayHistoryMu.Lock()
defer b.delayHistoryMu.Unlock()
if b.delayHistory == nil {
b.delayHistory = make(map[string][]DelayEntry)
}
h := b.delayHistory[tag]
h = append(h, DelayEntry{Time: time.Now(), Delay: delay})
if len(h) > maxDelayHistory {
h = h[len(h)-maxDelayHistory:]
}
b.delayHistory[tag] = h
}
func (b *Box) getHistory(tag string) []map[string]any {
b.delayHistoryMu.RLock()
defer b.delayHistoryMu.RUnlock()
entries := b.delayHistory[tag]
result := make([]map[string]any, len(entries))
for i, e := range entries {
result[i] = map[string]any{
"time": e.Time.Format(time.RFC3339),
"delay": e.Delay,
}
}
return result
}
func NewBox(ctx context.Context, options option.Options) (*Box, error) {