ConnLogs: return object with _diag for troubleshooting + frontend compat

API now returns:
{
  "logs": [...],    // ConnectionLog array (same fields as before)
  "_diag": [...]    // status.log paths/existence/parse status per instance
}

Frontend updated to handle both array (legacy) and object format.

This makes it easy to diagnose:
- Which status.log paths the backend looked at
- Whether files exist and their sizes
- How many entries were parsed
- Any parse errors

User just needs to: git pull && rebuild && restart on production.
This commit is contained in:
cnbugs
2026-08-10 00:12:00 +08:00
parent 81544d2335
commit 1706552b33
2 changed files with 29 additions and 8 deletions
+24 -7
View File
@@ -492,23 +492,36 @@ func (s *Server) listCerts(c *gin.Context) {
}
// ---- conn logs ----
func (s *Server) listConnLogs(c *gin.Context) {
// 诊断信息:返回每个实例 status.log 的存在情况和原始内容前 200 字节
instanceID := c.Query("instance")
// 1) 数据库里的历史日志(有断开时间的老连接)
history := s.Svc.Store.ListConnLogs(c.Query("instance"), 200)
history := s.Svc.Store.ListConnLogs(instanceID, 200)
// 2) 实时解析所有实例的 status.log,生成当前在线用户
var live []model.ConnectionLog
var diag []map[string]any
instances := s.Svc.Store.ListInstances()
for _, in := range instances {
if c.Query("instance") != "" && c.Query("instance") != in.ID {
if instanceID != "" && instanceID != in.ID {
continue
}
statusPath := filepath.Join(s.Svc.Cfg.InstanceDir(in.Name), "status.log")
entries, err := s.Svc.Ovm.ParseStatus(statusPath)
if err != nil {
continue
fi, statErr := os.Stat(statusPath)
d := map[string]any{
"instance": in.Name, "path": statusPath,
"exists": fi != nil, "size": int64(0),
}
if statErr == nil {
d["size"] = fi.Size()
}
entries, err := s.Svc.Ovm.ParseStatus(statusPath)
d["parsed"] = len(entries)
if err != nil {
d["error"] = err.Error()
}
diag = append(diag, d)
for _, e := range entries {
live = append(live, model.ConnectionLog{
InstanceID: in.ID,
@@ -535,7 +548,11 @@ func (s *Server) listConnLogs(c *gin.Context) {
}
merged = append(merged, h)
}
c.JSON(200, merged)
// 同时返回诊断信息(方便排查),前端忽略 _diag 字段
c.JSON(200, gin.H{
"logs": merged,
"_diag": diag,
})
}
// ---- backups ----
+5 -1
View File
@@ -33,7 +33,11 @@ const list = ref([])
const instances = ref([])
const instanceId = ref('')
async function load() { list.value = await Logs.conns(instanceId.value) }
async function load() {
const r = await Logs.conns(instanceId.value)
// 后端可能返回数组(旧)或 {logs:[...], _diag:[...]}(新)
list.value = Array.isArray(r) ? r : (r.logs || [])
}
function fmt(n) {
if (!n) return '0'
const u = ['B','KB','MB','GB','TB']; let i=0,v=n