mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-21 09:28:00 +00:00
fix: AUTO tier order ascending + stats/CSV export completeness + UI key-view toggle & exit affordance
- scheduler: BuildChain sorts tiers ascending so tier 1 (highest priority) is tried first; previously descending inverted the chain (P10-1..P10-5) - stats/api: handleStatsAPI limit→20000; CSV reads full audit via new Stats.AuditRecords (includes *.old rotation); key_names mapped by keyID() masked key; non-admin filter and keys-csv use masked keys - server: ring buffer NewStats(10000) - ui: dash-row card scroll area moved to table container (fix overflow below card); key view toggle (re-click same key returns to global) + kpi-exit affordance; rec-exit span - chat: chain-failure record now surfaces first failed tier; AUTO comment sync
This commit is contained in:
@ -395,6 +395,51 @@ func (s *Stats) Records(from, to int64, key string) []Req {
|
||||
return out
|
||||
}
|
||||
|
||||
// AuditRecords returns every request row from the audit file plus its rotated
|
||||
// .old files within the [from,to] unix-millisecond window, optionally for one
|
||||
// masked key id. Unlike Records it is not bounded by the in-memory ring, so it
|
||||
// yields a complete history for CSV export regardless of restarts or churn.
|
||||
func (s *Stats) AuditRecords(from, to int64, key string) []Req {
|
||||
s.mu.Lock()
|
||||
path := s.auditPath
|
||||
s.mu.Unlock()
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
files := []string{path}
|
||||
if olds, err := filepath.Glob(path + ".*.old"); err == nil {
|
||||
files = append(files, olds...)
|
||||
}
|
||||
var out []Req
|
||||
for _, p := range files {
|
||||
f, err := os.Open(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
sc := bufio.NewScanner(f)
|
||||
sc.Buffer(make([]byte, 64*1024), 16*1024*1024)
|
||||
for sc.Scan() {
|
||||
var r Req
|
||||
if json.Unmarshal(sc.Bytes(), &r) != nil || r.Type == "" {
|
||||
continue
|
||||
}
|
||||
if key != "" && r.Key != key {
|
||||
continue
|
||||
}
|
||||
if from > 0 && r.Time < from {
|
||||
continue
|
||||
}
|
||||
if to > 0 && r.Time > to {
|
||||
continue
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Time < out[j].Time })
|
||||
return out
|
||||
}
|
||||
|
||||
// Snapshot returns the whole dashboard payload; when key != "" the records
|
||||
// and aggregate views are restricted to that gateway key.
|
||||
func (s *Stats) Snapshot(limit int, key string) map[string]interface{} {
|
||||
|
||||
Reference in New Issue
Block a user