✨ feat(status): 新增请求日志并重设计状态页

- 新增 server.request_log 配置:记录业务请求元数据(IP/方法/路径/状态/耗时,
  key 自动脱敏)与 4xx/5xx 错误摘要(前 4KB),按保留天数自动清理
- 移除 /self-info 与 /vacuum 接口及相关文档
- 状态页重设计:毛玻璃卡片+吸顶玻璃栏、服务状态条、KPI 卡与请求分类
  条形图、可折叠 API 文档分组、行内测试面板;深浅色分别调校,
  含 reduced-motion / reduced-transparency / 无 backdrop-filter 兜底
This commit is contained in:
chenxin committed 2026-10-09 18:03:02 +08:00
1 parent bf49805bb6
commit bfb4290c15
11 files changed
+1060 -838

No files matched your search

+25 -30
View File
@@ -2,7 +2,6 @@ package handlers
import (
_ "embed"
"encoding/json"
"fanqie/internal/algos"
"fanqie/internal/config"
"fanqie/internal/fqapi"
@@ -12,35 +11,6 @@ import (
"time"
)
// HandleVacuum 处理数据库压缩请求
func HandleVacuum(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
// 只允许 POST 请求
if r.Method != http.MethodPost {
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "仅支持 POST 请求",
})
return
}
// 执行 VACUUM
err := fqapi.VacuumDatabase()
if err != nil {
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "压缩失败: " + err.Error(),
})
return
}
json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "数据库压缩完成",
})
}
// 状态页模板(embed 内嵌,动态数据由 html/template 自动转义)
//
//go:embed templates/status.html
@@ -86,12 +56,28 @@ func HandleStatus(w http.ResponseWriter, r *http.Request) {
// 获取设备密钥池状态
poolStatus := getDeviceKeyPoolStatus()
// 获取最近请求(日志未启用时为空)
var recent []map[string]interface{}
for _, e := range fqapi.GetRecentRequests(20) {
recent = append(recent, map[string]interface{}{
"Time": time.Unix(e.Ts, 0).Format("15:04:05"),
"IP": e.IP,
"Method": e.Method,
"Path": e.Path,
"Query": truncateStr(e.Query, 80),
"Status": e.Status,
"IsErr": e.Status >= 400,
"Duration": fmt.Sprintf("%dms", e.DurationMs),
})
}
statusTmpl.Execute(w, map[string]interface{}{
"NowTime": time.Now().Format("2006-01-02 15:04:05"),
"Uptime": uptimeStr,
"StartTime": startTime.Format("2006-01-02 15:04:05"),
"Signature": signatureDetails,
"DBTotal": getDBTotalSize(),
"DBUsedPct": getDBUsagePercentage(),
"DBUsed": getDBUsedSize(),
"DBFree": getDBFreeSize(),
"PoolStatus": poolStatus["status"],
@@ -112,9 +98,18 @@ func HandleStatus(w http.ResponseWriter, r *http.Request) {
"CacheStatus": getCacheStatus(),
"CleanupStatus": getCleanupStatus(),
"CleanupInterval": getCleanupInterval(),
"RecentRequests": recent,
})
}
// truncateStr 截断字符串,超长加省略号
func truncateStr(s string, n int) string {
if len(s) <= n {
return s
}
return s[:n] + "…"
}
// getCacheStatus 获取缓存状态
func getCacheStatus() string {
cfg := config.GetConfig()