统一单入口 Go 工程与前端依赖目录,增加后台供应商配置、候选审核、计划预算、成交冲正、持仓复盘和站内通知。接入策略版本、Python 回测、可配置 A 股公开行情及 zap 文件轮转日志,补充迁移、契约与验证。
This commit is contained in:
@@ -3,7 +3,7 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"go.uber.org/zap"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"git.sundynix.cn/Blizzard/Veyra/internal/service"
|
||||
)
|
||||
|
||||
func NewRouter(health *service.HealthService, logger *slog.Logger, identity IdentityOptions) http.Handler {
|
||||
func NewRouter(health *service.HealthService, logger *zap.Logger, identity IdentityOptions) http.Handler {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
r.Use(func(c *gin.Context) {
|
||||
@@ -29,10 +29,27 @@ func NewRouter(health *service.HealthService, logger *slog.Logger, identity Iden
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
logger.Error("request panic", "request_id", requestID)
|
||||
logger.Error("request panic", zap.String("request_id", requestID))
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": gin.H{"code": "INTERNAL_ERROR", "message": "Internal server error", "request_id": requestID}})
|
||||
}
|
||||
logger.Info("http request", "method", c.Request.Method, "route", c.FullPath(), "status", c.Writer.Status(), "duration_ms", time.Since(start).Milliseconds(), "request_id", requestID)
|
||||
route := c.FullPath()
|
||||
if route == "" {
|
||||
route = "/<unmatched>"
|
||||
if c.Request.URL.Path == "/" {
|
||||
route = "/"
|
||||
} else if strings.HasPrefix(c.Request.URL.Path, "/assets/") {
|
||||
route = "/assets/*"
|
||||
}
|
||||
}
|
||||
fields := []zap.Field{zap.String("method", c.Request.Method), zap.String("route", route), zap.Int("status", c.Writer.Status()), zap.Int64("duration_ms", time.Since(start).Milliseconds()), zap.String("request_id", requestID)}
|
||||
switch {
|
||||
case c.Writer.Status() >= 500:
|
||||
logger.Error("HTTP request", fields...)
|
||||
case c.Writer.Status() >= 400:
|
||||
logger.Warn("HTTP request", fields...)
|
||||
default:
|
||||
logger.Info("HTTP request", fields...)
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
})
|
||||
@@ -48,6 +65,14 @@ func NewRouter(health *service.HealthService, logger *slog.Logger, identity Iden
|
||||
r.GET("/readyz", check)
|
||||
r.GET("/api/v1/system/health", check)
|
||||
bindIdentity(r, identity)
|
||||
bindProviders(r, identity)
|
||||
bindCandidates(r, identity)
|
||||
bindTradePlans(r, identity)
|
||||
bindTradeFills(r, identity)
|
||||
bindNotifications(r, identity)
|
||||
bindStrategies(r, identity)
|
||||
bindBacktests(r, identity)
|
||||
bindMarket(r, identity)
|
||||
console := adminui.Handler()
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
if !strings.HasPrefix(c.Request.URL.Path, "/api/") && c.Request.URL.Path != "/api" {
|
||||
|
||||
Reference in New Issue
Block a user