feat: add Docker support and logging enhancements
- Introduced Dockerfile and .dockerignore for containerization of the backend service. - Added logging configuration with support for daily rolling logs and customizable log levels. - Enhanced the server to utilize structured logging with zap, including detailed request and error logging. - Updated configuration to include logging parameters and proxy settings. - Implemented tests for logging configuration and proxy settings.
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"monica-go-completion-backend/internal/completion"
|
||||
)
|
||||
@@ -62,10 +63,35 @@ func registerWSRoutes(router *gin.Engine, service CompletionService, opts RouteO
|
||||
handler := func(c *gin.Context, defaultLanguage string) {
|
||||
conn, err := wsUpgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
zap.L().Warn(
|
||||
"ws upgrade failed",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("path", c.Request.URL.Path),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
traceID := traceIDFromGin(c)
|
||||
zap.L().Info(
|
||||
"ws connection opened",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("path", c.Request.URL.Path),
|
||||
zap.String("language", defaultLanguage),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
)
|
||||
defer func() {
|
||||
zap.L().Info(
|
||||
"ws connection closed",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("path", c.Request.URL.Path),
|
||||
zap.String("language", defaultLanguage),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
)
|
||||
}()
|
||||
|
||||
conn.SetReadLimit(opts.MaxBodyBytes)
|
||||
|
||||
var writeMu sync.Mutex
|
||||
@@ -74,9 +100,15 @@ func registerWSRoutes(router *gin.Engine, service CompletionService, opts RouteO
|
||||
// 单连接串行读取消息,写操作通过 writeMu 保证并发安全。
|
||||
_, payload, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
zap.L().Info(
|
||||
"ws read loop ended",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("path", c.Request.URL.Path),
|
||||
zap.Error(err),
|
||||
)
|
||||
break
|
||||
}
|
||||
handleWSMessage(conn, &writeMu, service, payload, defaultLanguage, opts)
|
||||
handleWSMessage(conn, &writeMu, service, payload, defaultLanguage, traceID, c.ClientIP(), opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,14 +127,22 @@ func handleWSMessage(
|
||||
service CompletionService,
|
||||
payload []byte,
|
||||
defaultLanguage string,
|
||||
traceID string,
|
||||
clientIP string,
|
||||
opts RouteOptions,
|
||||
) {
|
||||
if tryHandleRPCMessage(conn, writeMu, service, payload, defaultLanguage, opts) {
|
||||
if tryHandleRPCMessage(conn, writeMu, service, payload, defaultLanguage, traceID, clientIP, opts) {
|
||||
return
|
||||
}
|
||||
|
||||
var req wsCompletionRequest
|
||||
if err := json.Unmarshal(payload, &req); err != nil {
|
||||
zap.L().Warn(
|
||||
"ws invalid json payload",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("clientIP", clientIP),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendWSResponse(conn, writeMu, wsCompletionResponse{
|
||||
ID: "",
|
||||
Error: "invalid JSON payload",
|
||||
@@ -113,7 +153,7 @@ func handleWSMessage(
|
||||
req.Language = defaultLanguage
|
||||
}
|
||||
|
||||
processWSCompletion(conn, writeMu, service, req, opts)
|
||||
processWSCompletion(conn, writeMu, service, req, traceID, clientIP, opts)
|
||||
}
|
||||
|
||||
// tryHandleRPCMessage 处理 JSON-RPC 2.0 请求,返回 true 表示消息已消费。
|
||||
@@ -123,6 +163,8 @@ func tryHandleRPCMessage(
|
||||
service CompletionService,
|
||||
payload []byte,
|
||||
defaultLanguage string,
|
||||
traceID string,
|
||||
clientIP string,
|
||||
opts RouteOptions,
|
||||
) bool {
|
||||
var rpcReq wsRPCRequest
|
||||
@@ -148,6 +190,13 @@ func tryHandleRPCMessage(
|
||||
|
||||
var req wsCompletionRequest
|
||||
if err := json.Unmarshal(rpcReq.Params, &req); err != nil {
|
||||
zap.L().Warn(
|
||||
"ws rpc invalid params",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("clientIP", clientIP),
|
||||
zap.String("method", rpcReq.Method),
|
||||
zap.Error(err),
|
||||
)
|
||||
// 参数反序列化失败按 invalid params 处理。
|
||||
sendWSRPCResponse(conn, writeMu, wsRPCResponse{
|
||||
JSONRPC: "2.0",
|
||||
@@ -179,6 +228,16 @@ func tryHandleRPCMessage(
|
||||
Character: req.Character,
|
||||
})
|
||||
if err != nil {
|
||||
zap.L().Warn(
|
||||
"ws rpc completion failed",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("clientIP", clientIP),
|
||||
zap.String("method", rpcReq.Method),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("uri", req.URI),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendWSRPCResponse(conn, writeMu, wsRPCResponse{
|
||||
JSONRPC: "2.0",
|
||||
ID: rpcReq.ID,
|
||||
@@ -204,6 +263,8 @@ func processWSCompletion(
|
||||
writeMu *sync.Mutex,
|
||||
service CompletionService,
|
||||
req wsCompletionRequest,
|
||||
traceID string,
|
||||
clientIP string,
|
||||
opts RouteOptions,
|
||||
) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), opts.RequestTimeout)
|
||||
@@ -237,6 +298,17 @@ func processWSCompletion(
|
||||
ownerID = ownedErr.OwnerID
|
||||
}
|
||||
}
|
||||
zap.L().Warn(
|
||||
"ws completion failed",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("clientIP", clientIP),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("uri", req.URI),
|
||||
zap.String("routeTo", routeTo),
|
||||
zap.String("ownerId", ownerID),
|
||||
zap.Error(err),
|
||||
)
|
||||
sendWSResponse(conn, writeMu, wsCompletionResponse{
|
||||
ID: req.ID,
|
||||
RouteTo: routeTo,
|
||||
@@ -245,6 +317,15 @@ func processWSCompletion(
|
||||
})
|
||||
return
|
||||
}
|
||||
zap.L().Info(
|
||||
"ws completion success",
|
||||
zap.String("traceId", traceID),
|
||||
zap.String("clientIP", clientIP),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("uri", req.URI),
|
||||
zap.Int("items", len(resp.Items)),
|
||||
)
|
||||
|
||||
sendWSResponse(conn, writeMu, wsCompletionResponse{
|
||||
ID: req.ID,
|
||||
|
||||
Reference in New Issue
Block a user