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:
@@ -4,9 +4,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"monica-go-completion-backend/internal/completion"
|
||||
)
|
||||
@@ -67,6 +69,13 @@ func RegisterRoutes(router *gin.Engine, service CompletionService, options ...Ro
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, opts.MaxBodyBytes)
|
||||
var req completion.Request
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
zap.L().Warn(
|
||||
"invalid completion json payload",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("routeLanguage", c.Param("language")),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.Error(err),
|
||||
)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON payload"})
|
||||
return
|
||||
}
|
||||
@@ -84,19 +93,51 @@ func RegisterRoutes(router *gin.Engine, service CompletionService, options ...Ro
|
||||
resp, err := service.Complete(ctx, req)
|
||||
if err != nil {
|
||||
if errors.Is(err, completion.ErrInvalidRequest) {
|
||||
zap.L().Warn(
|
||||
"completion request invalid",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("uri", req.URI),
|
||||
zap.Error(err),
|
||||
)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if errors.Is(err, completion.ErrUnsupportedLanguage) {
|
||||
zap.L().Warn(
|
||||
"completion language not supported",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.Error(err),
|
||||
)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if errors.Is(err, completion.ErrTooManySessions) {
|
||||
zap.L().Warn(
|
||||
"completion rejected due to session limit",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.Error(err),
|
||||
)
|
||||
c.JSON(http.StatusTooManyRequests, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
var ownedErr *completion.ErrSessionOwnedByOtherInstance
|
||||
if errors.As(err, &ownedErr) {
|
||||
zap.L().Info(
|
||||
"completion routed to session owner",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("ownerId", ownedErr.OwnerID),
|
||||
zap.String("routeTo", ownedErr.OwnerEndpoint),
|
||||
)
|
||||
if ownedErr.OwnerEndpoint != "" {
|
||||
c.Header("X-LSP-Route-To", ownedErr.OwnerEndpoint)
|
||||
}
|
||||
@@ -107,9 +148,28 @@ func RegisterRoutes(router *gin.Engine, service CompletionService, options ...Ro
|
||||
})
|
||||
return
|
||||
}
|
||||
zap.L().Error(
|
||||
"completion failed",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("uri", req.URI),
|
||||
zap.Error(err),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "completion failed"})
|
||||
return
|
||||
}
|
||||
zap.L().Info(
|
||||
"completion success",
|
||||
zap.String("traceId", traceIDFromGin(c)),
|
||||
zap.String("clientIP", c.ClientIP()),
|
||||
zap.String("language", req.Language),
|
||||
zap.String("sessionId", req.SessionID),
|
||||
zap.String("uri", req.URI),
|
||||
zap.Int("items", len(resp.Items)),
|
||||
zap.Bool("isIncomplete", resp.IsIncomplete),
|
||||
)
|
||||
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
@@ -118,3 +178,14 @@ func RegisterRoutes(router *gin.Engine, service CompletionService, options ...Ro
|
||||
handleCompletion(c)
|
||||
})
|
||||
}
|
||||
|
||||
func traceIDFromGin(c *gin.Context) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
traceID := strings.TrimSpace(c.GetString("traceId"))
|
||||
if traceID != "" {
|
||||
return traceID
|
||||
}
|
||||
return strings.TrimSpace(c.GetString("requestId"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user