package handler import ( "encoding/json" "fmt" "net/http" "time" "ckwk/internal/dto" "ckwk/pkg/log" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) var debugLogUpgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func DebugLogs(ctx *gin.Context) { ctx.JSON(http.StatusOK, dto.Success(map[string]any{ "list": log.Entries(), })) } func DebugLogsDownload(ctx *gin.Context) { entries := log.Entries() content, err := json.MarshalIndent(entries, "", " ") if err != nil { ctx.JSON(http.StatusInternalServerError, dto.Error(500, "日志导出失败")) return } filename := fmt.Sprintf("wk-debug-logs-%s.json", time.Now().Format("20060102-150405")) ctx.Header("Content-Type", "application/json; charset=utf-8") ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) ctx.Data(http.StatusOK, "application/json; charset=utf-8", content) } func DebugLogWS(ctx *gin.Context) { conn, err := debugLogUpgrader.Upgrade(ctx.Writer, ctx.Request, nil) if err != nil { return } defer conn.Close() subID, ch := log.Subscribe() defer log.Unsubscribe(subID) for _, entry := range log.Entries() { if err := conn.WriteJSON(entry); err != nil { return } } done := make(chan struct{}) go func() { defer close(done) for { if _, _, err := conn.ReadMessage(); err != nil { return } } }() ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for { select { case <-done: return case entry, ok := <-ch: if !ok { return } if err := conn.WriteJSON(entry); err != nil { return } case <-ticker.C: if err := conn.WriteMessage(websocket.PingMessage, []byte("ping")); err != nil { return } } } }