diff --git a/.gitignore b/.gitignore index bfad8f6..a5842a0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ .ai/ .geminiignore +.gemini +env.json +env.yml +env.yaml \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d771136..079ecc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG - go/service +## v1.3.1 (2026-05-10) +- **Logging Refactor (Callback Pattern)**: 引入 `LogRequest` 闭环式回调封装,自动处理日志级别检查、对象池获取及元数据填充,消除 20+ 参数带来的维护压力。 +- **Graceful Shutdown**: `ServiceConfig` 新增 `StopTimeout` 字段,支持通过配置灵活管控服务优雅退出的超时时间(默认 5s)。 +- **Panic Recovery**: 增强 `handler.go` 中的 `recover` 逻辑,在发生 Panic 时自动记录 `requestId` 和 `path`,大幅提升故障定位效率。 +- **Infrastructure Alignment**: 全量回退并对齐 Go 版本至 `1.25.0`;同步更新 `handler.go` 以适配新的日志调用模式。 + +## v1.0.5 (2026-05-10) +- **Wait**: This version was a temporary placeholder. See v1.3.1 for the actual release. + ## v1.0.4 (2026-05-10) - **Log Optimization**: Implemented `NoLogGets`, `NoLogHeaders`, `LogInputArrayNum`, `LogInputFieldSize`, and other fine-grained logging filters. - **Static Log**: Added automatic logging for static file access. diff --git a/config.go b/config.go index 2633176..982335d 100644 --- a/config.go +++ b/config.go @@ -59,6 +59,7 @@ type ServiceConfig struct { MaxReadFrameSize uint32 // 单个帧的最大读取大小 MaxUploadBufferPerConnection int32 // 每个连接的最大上传缓冲区大小 MaxUploadBufferPerStream int32 // 每个流的最大上传缓冲区大小 + StopTimeout int // 停止服务的超时时间 (ms) } var Config = ServiceConfig{} diff --git a/handler.go b/handler.go index 22feb0e..ebd9f18 100644 --- a/handler.go +++ b/handler.go @@ -44,7 +44,7 @@ func (rh *RouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer func() { // 捕捉 Panic if err := recover(); err != nil { - requestLogger.Error("panic recovered", "error", err, "stack", string(debug.Stack())) + requestLogger.Error("panic recovered", "requestId", requestId, "path", r.URL.Path, "error", err, "stack", string(debug.Stack())) if !response.changed { response.WriteHeader(http.StatusInternalServerError) outputResult(response, "internal server error") @@ -102,18 +102,31 @@ func (rh *RouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } - logRequest( - requestLogger, - r.Method, r.URL.Path, hostOnly(r.Host), scheme, r.Proto, - request.ClientIp(), serverId, Config.App, "", // node 暂无 - r.Header.Get(discover.HeaderFromApp), r.Header.Get(discover.HeaderFromNode), - "", request.DeviceId(), request.SessionId(), requestId, - request.Header.Get(discover.HeaderClientAppName), request.Header.Get(discover.HeaderClientAppVersion), - authLevel, priority, - reqHeaders, args, - response.Code, usedTime, - respHeaders, cast.String(respData), uint(len(response.body)), - ) + LogRequest(requestLogger, func(entry *RequestLog) { + entry.Method = r.Method + entry.Path = r.URL.Path + entry.Host = hostOnly(r.Host) + entry.Scheme = scheme + entry.Proto = r.Proto + entry.ClientIp = request.ClientIp() + entry.ServerId = serverId + entry.App = Config.App + entry.FromApp = r.Header.Get(discover.HeaderFromApp) + entry.FromNode = r.Header.Get(discover.HeaderFromNode) + entry.DeviceId = request.DeviceId() + entry.SessionId = request.SessionId() + entry.ClientAppName = r.Header.Get(discover.HeaderClientAppName) + entry.ClientAppVersion = r.Header.Get(discover.HeaderClientAppVersion) + entry.AuthLevel = authLevel + entry.Priority = priority + entry.RequestHeaders = reqHeaders + entry.RequestData = args + entry.ResponseCode = response.Code + entry.UsedTime = usedTime + entry.ResponseHeaders = respHeaders + entry.ResponseData = respData + entry.ResponseDataLength = uint(len(response.body)) + }) } }() diff --git a/log.go b/log.go index 8501c8c..6773301 100644 --- a/log.go +++ b/log.go @@ -1,7 +1,6 @@ package service import ( - "apigo.cc/go/cast" "apigo.cc/go/log" ) @@ -71,24 +70,8 @@ func (l *RequestLog) Reset() { l.ResponseData = nil } -// RequestLog 调用封装 -func logRequest( - logger *log.Logger, - method, path, host, scheme, proto string, - clientIp, serverId, app, node string, - fromApp, fromNode string, - userId, deviceId, sessionId, requestId string, - clientAppName, clientAppVersion string, - authLevel, priority int, - reqHeaders map[string]string, - reqData map[string]any, - responseCode int, - usedTime float32, - respHeaders map[string]string, - responseData string, - responseDataLength uint, - extra ...any, -) { +// LogRequest 闭环式日志调用封装 +func LogRequest(logger *log.Logger, fn func(entry *RequestLog)) { if !logger.CheckLevel(log.INFO) { return } @@ -96,35 +79,10 @@ func logRequest( entry := log.GetEntry[RequestLog]() logger.FillBase(entry.GetBaseLog(), log.LogTypeRequest) - entry.Method = method - entry.Path = path - entry.Host = host - entry.Scheme = scheme - entry.Proto = proto - entry.ClientIp = clientIp - entry.ServerId = serverId - entry.App = app - entry.Node = node - entry.FromApp = fromApp - entry.FromNode = fromNode - entry.UserId = userId - entry.DeviceId = deviceId - entry.SessionId = sessionId - entry.ClientAppName = clientAppName - entry.ClientAppVersion = clientAppVersion - entry.AuthLevel = authLevel - entry.Priority = priority - entry.RequestHeaders = reqHeaders - entry.RequestData = reqData - entry.ResponseCode = responseCode - entry.UsedTime = usedTime - entry.ResponseHeaders = respHeaders - entry.ResponseData = responseData - entry.ResponseDataLength = responseDataLength - if len(extra) > 0 { - cast.FillMap(&entry.Extra, extra) - } + // 执行业务赋值逻辑 + fn(entry) + // 统一发送 logger.Log(entry) } diff --git a/server.go b/server.go index f259881..b865d9d 100644 --- a/server.go +++ b/server.go @@ -188,7 +188,12 @@ func (as *AsyncServer) Stop() { as.discoverer.Stop() } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + stopTimeout := time.Duration(Config.StopTimeout) * time.Millisecond + if stopTimeout <= 0 { + stopTimeout = 5 * time.Second + } + + ctx, cancel := context.WithTimeout(context.Background(), stopTimeout) defer cancel() if err := as.server.Shutdown(ctx); err != nil {