mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 20:47:49 +08:00
ekg stats: add 6h/24h/7d window filter and webui selector for time-windowed insights
This commit is contained in:
@@ -1639,6 +1639,21 @@ func (s *RegistryServer) handleWebUIEKGStats(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
workspace := strings.TrimSpace(s.workspacePath)
|
||||
ekgPath := filepath.Join(workspace, "memory", "ekg-events.jsonl")
|
||||
window := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("window")))
|
||||
windowDur := 24 * time.Hour
|
||||
switch window {
|
||||
case "6h":
|
||||
windowDur = 6 * time.Hour
|
||||
case "24h", "":
|
||||
windowDur = 24 * time.Hour
|
||||
case "7d":
|
||||
windowDur = 7 * 24 * time.Hour
|
||||
}
|
||||
selectedWindow := window
|
||||
if selectedWindow == "" {
|
||||
selectedWindow = "24h"
|
||||
}
|
||||
cutoff := time.Now().UTC().Add(-windowDur)
|
||||
b, _ := os.ReadFile(ekgPath)
|
||||
lines := strings.Split(string(b), "\n")
|
||||
if len(lines) > 0 && lines[len(lines)-1] == "" {
|
||||
@@ -1667,6 +1682,14 @@ func (s *RegistryServer) handleWebUIEKGStats(w http.ResponseWriter, r *http.Requ
|
||||
if json.Unmarshal([]byte(ln), &row) != nil {
|
||||
continue
|
||||
}
|
||||
ts := strings.TrimSpace(fmt.Sprintf("%v", row["time"]))
|
||||
if ts != "" {
|
||||
if tm, err := time.Parse(time.RFC3339, ts); err == nil {
|
||||
if tm.Before(cutoff) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
provider := strings.TrimSpace(fmt.Sprintf("%v", row["provider"]))
|
||||
status := strings.ToLower(strings.TrimSpace(fmt.Sprintf("%v", row["status"])))
|
||||
errSig := strings.TrimSpace(fmt.Sprintf("%v", row["errsig"]))
|
||||
@@ -1731,6 +1754,7 @@ func (s *RegistryServer) handleWebUIEKGStats(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"ok": true,
|
||||
"window": selectedWindow,
|
||||
"provider_top": toTopScore(providerScore, 5),
|
||||
"provider_top_workload": toTopScore(providerScoreWorkload, 5),
|
||||
"errsig_top": toTopCount(errSigCount, 5),
|
||||
|
||||
@@ -47,6 +47,7 @@ const TaskAudit: React.FC = () => {
|
||||
const [ekgSourceStats, setEkgSourceStats] = useState<Record<string, number>>({});
|
||||
const [ekgChannelStats, setEkgChannelStats] = useState<Record<string, number>>({});
|
||||
const [ekgEscalationCount, setEkgEscalationCount] = useState<number>(0);
|
||||
const [ekgWindow, setEkgWindow] = useState<'6h' | '24h' | '7d'>('24h');
|
||||
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
@@ -67,7 +68,8 @@ const TaskAudit: React.FC = () => {
|
||||
} else {
|
||||
setDailyReport('');
|
||||
}
|
||||
const ekgUrl = `/webui/api/ekg_stats${q || ''}`;
|
||||
const ekgJoin = q ? `${q}&window=${encodeURIComponent(ekgWindow)}` : `?window=${encodeURIComponent(ekgWindow)}`;
|
||||
const ekgUrl = `/webui/api/ekg_stats${ekgJoin}`;
|
||||
const er = await fetch(ekgUrl);
|
||||
if (er.ok) {
|
||||
const ej = await er.json();
|
||||
@@ -89,7 +91,7 @@ const TaskAudit: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => { fetchData(); }, [q, reportDate]);
|
||||
useEffect(() => { fetchData(); }, [q, reportDate, ekgWindow]);
|
||||
|
||||
|
||||
|
||||
@@ -149,7 +151,14 @@ const TaskAudit: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="border border-zinc-800 rounded-xl bg-zinc-900/40 p-3 text-sm">
|
||||
<div className="text-xs text-zinc-400 uppercase tracking-wider mb-2">EKG Insights</div>
|
||||
<div className="flex items-center justify-between gap-2 mb-2">
|
||||
<div className="text-xs text-zinc-400 uppercase tracking-wider">EKG Insights</div>
|
||||
<select value={ekgWindow} onChange={(e)=>setEkgWindow(e.target.value as '6h' | '24h' | '7d')} className="bg-zinc-900 border border-zinc-700 rounded px-2 py-1 text-xs">
|
||||
<option value="6h">6h</option>
|
||||
<option value="24h">24h</option>
|
||||
<option value="7d">7d</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-3 text-xs">
|
||||
<div className="rounded-lg border border-zinc-800 bg-zinc-950/40 p-2">
|
||||
<div className="text-zinc-500 mb-1">Escalations</div>
|
||||
|
||||
Reference in New Issue
Block a user