Refactor service logging to callback pattern, add configurable StopTimeout and enhance panic context (by AI)
This commit is contained in:
parent
8ed2986eb9
commit
c207bdd400
4
.gitignore
vendored
4
.gitignore
vendored
@ -3,3 +3,7 @@
|
|||||||
.ai/
|
.ai/
|
||||||
|
|
||||||
.geminiignore
|
.geminiignore
|
||||||
|
.gemini
|
||||||
|
env.json
|
||||||
|
env.yml
|
||||||
|
env.yaml
|
||||||
@ -1,5 +1,14 @@
|
|||||||
# CHANGELOG - go/service
|
# 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)
|
## v1.0.4 (2026-05-10)
|
||||||
- **Log Optimization**: Implemented `NoLogGets`, `NoLogHeaders`, `LogInputArrayNum`, `LogInputFieldSize`, and other fine-grained logging filters.
|
- **Log Optimization**: Implemented `NoLogGets`, `NoLogHeaders`, `LogInputArrayNum`, `LogInputFieldSize`, and other fine-grained logging filters.
|
||||||
- **Static Log**: Added automatic logging for static file access.
|
- **Static Log**: Added automatic logging for static file access.
|
||||||
|
|||||||
@ -59,6 +59,7 @@ type ServiceConfig struct {
|
|||||||
MaxReadFrameSize uint32 // 单个帧的最大读取大小
|
MaxReadFrameSize uint32 // 单个帧的最大读取大小
|
||||||
MaxUploadBufferPerConnection int32 // 每个连接的最大上传缓冲区大小
|
MaxUploadBufferPerConnection int32 // 每个连接的最大上传缓冲区大小
|
||||||
MaxUploadBufferPerStream int32 // 每个流的最大上传缓冲区大小
|
MaxUploadBufferPerStream int32 // 每个流的最大上传缓冲区大小
|
||||||
|
StopTimeout int // 停止服务的超时时间 (ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
var Config = ServiceConfig{}
|
var Config = ServiceConfig{}
|
||||||
|
|||||||
39
handler.go
39
handler.go
@ -44,7 +44,7 @@ func (rh *RouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
// 捕捉 Panic
|
// 捕捉 Panic
|
||||||
if err := recover(); err != nil {
|
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 {
|
if !response.changed {
|
||||||
response.WriteHeader(http.StatusInternalServerError)
|
response.WriteHeader(http.StatusInternalServerError)
|
||||||
outputResult(response, "internal server error")
|
outputResult(response, "internal server error")
|
||||||
@ -102,18 +102,31 @@ func (rh *RouteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logRequest(
|
LogRequest(requestLogger, func(entry *RequestLog) {
|
||||||
requestLogger,
|
entry.Method = r.Method
|
||||||
r.Method, r.URL.Path, hostOnly(r.Host), scheme, r.Proto,
|
entry.Path = r.URL.Path
|
||||||
request.ClientIp(), serverId, Config.App, "", // node 暂无
|
entry.Host = hostOnly(r.Host)
|
||||||
r.Header.Get(discover.HeaderFromApp), r.Header.Get(discover.HeaderFromNode),
|
entry.Scheme = scheme
|
||||||
"", request.DeviceId(), request.SessionId(), requestId,
|
entry.Proto = r.Proto
|
||||||
request.Header.Get(discover.HeaderClientAppName), request.Header.Get(discover.HeaderClientAppVersion),
|
entry.ClientIp = request.ClientIp()
|
||||||
authLevel, priority,
|
entry.ServerId = serverId
|
||||||
reqHeaders, args,
|
entry.App = Config.App
|
||||||
response.Code, usedTime,
|
entry.FromApp = r.Header.Get(discover.HeaderFromApp)
|
||||||
respHeaders, cast.String(respData), uint(len(response.body)),
|
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))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
52
log.go
52
log.go
@ -1,7 +1,6 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"apigo.cc/go/cast"
|
|
||||||
"apigo.cc/go/log"
|
"apigo.cc/go/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,24 +70,8 @@ func (l *RequestLog) Reset() {
|
|||||||
l.ResponseData = nil
|
l.ResponseData = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestLog 调用封装
|
// LogRequest 闭环式日志调用封装
|
||||||
func logRequest(
|
func LogRequest(logger *log.Logger, fn func(entry *RequestLog)) {
|
||||||
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,
|
|
||||||
) {
|
|
||||||
if !logger.CheckLevel(log.INFO) {
|
if !logger.CheckLevel(log.INFO) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -96,35 +79,10 @@ func logRequest(
|
|||||||
entry := log.GetEntry[RequestLog]()
|
entry := log.GetEntry[RequestLog]()
|
||||||
logger.FillBase(entry.GetBaseLog(), log.LogTypeRequest)
|
logger.FillBase(entry.GetBaseLog(), log.LogTypeRequest)
|
||||||
|
|
||||||
entry.Method = method
|
// 执行业务赋值逻辑
|
||||||
entry.Path = path
|
fn(entry)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 统一发送
|
||||||
logger.Log(entry)
|
logger.Log(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -188,7 +188,12 @@ func (as *AsyncServer) Stop() {
|
|||||||
as.discoverer.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()
|
defer cancel()
|
||||||
|
|
||||||
if err := as.server.Shutdown(ctx); err != nil {
|
if err := as.server.Shutdown(ctx); err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user