feat(platform): 日志管理 - 统一日志出口并屏蔽查询与 Agent 流式事件日志

新增 internal/logging,slog、标准库 log、GORM 与 Gin 访问日志共用同一 Handler,由 CANVAS_LOG_LEVEL / CANVAS_LOG_FORMAT 控制。info 级别不再输出成功的查询类请求、成功 SQL、message_end 等 Agent 流式事件和常规画布自动保存;4xx/5xx、慢请求、慢 SQL、SQL 失败与 panic 仍会记录,SQL 不内联参数值。
This commit is contained in:
ddcat666
2026-09-30 03:33:34 +08:00
parent b7ff958c2d
commit a0f025aa96
21 changed files with 602 additions and 44 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log"
"log/slog"
"net"
"net/http"
"net/url"
@@ -17,6 +18,7 @@ import (
"infinite-canvas/backend/internal/database"
"infinite-canvas/backend/internal/handler"
"infinite-canvas/backend/internal/logging"
"infinite-canvas/backend/internal/repository"
"infinite-canvas/backend/internal/service"
"infinite-canvas/backend/internal/updaterclient"
@@ -25,6 +27,11 @@ import (
)
func main() {
logConfig, err := logging.ConfigFromEnv()
if err != nil {
log.Fatal(err)
}
logging.Setup(logConfig)
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
if err := run(ctx); err != nil {
@@ -95,14 +102,13 @@ func run(ctx context.Context) error {
return err
}
if summary, err := svc.MigrateLegacyStorage(); err != nil {
log.Printf("storage migration skipped after error: %v", err)
slog.Warn("storage migration skipped after error", "error", err)
} else if summary.Backup != "" {
log.Printf("storage migration completed: tasks=%d assets=%d projects=%d backup=%s", summary.Tasks, summary.Assets, summary.Projects, summary.Backup)
slog.Info("storage migration completed", "tasks", summary.Tasks, "assets", summary.Assets, "projects", summary.Projects, "backup", summary.Backup)
}
r := gin.New()
r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
return fmt.Sprintf("%s - [%s] \"%s %s\" %d %s %s\n", param.ClientIP, param.TimeStamp.Format(time.RFC3339), param.Method, redactCanvasSharePath(param.Path), param.StatusCode, param.Latency, param.ErrorMessage)
}), gin.Recovery())
// 访问日志:成功的查询类请求只在 debug 级别输出,避免轮询和列表查询把日志打爆。
r.Use(logging.AccessLog(redactCanvasSharePath), logging.Recovery())
r.Use(handler.RequestCorrelationMiddleware())
corsMiddleware, err := cors()
if err != nil {
@@ -133,7 +139,7 @@ func run(ctx context.Context) error {
status.markStarted()
serveErr := make(chan error, 1)
go func() { serveErr <- httpServer.Serve(listener) }()
log.Printf("backend listening on %s", addr)
slog.Info("backend listening", "addr", addr)
var serveFailure error
select {
@@ -163,7 +169,7 @@ func run(ctx context.Context) error {
if err := errors.Join(shutdownFailures...); err != nil {
return err
}
log.Printf("backend stopped gracefully")
slog.Info("backend stopped gracefully")
return nil
}