mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-18 20:30:51 +08:00
feat(logging): scope request ID tracking to AI API endpoints
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -14,28 +15,42 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// aiAPIPrefixes defines path prefixes for AI API requests that should have request ID tracking.
|
||||||
|
var aiAPIPrefixes = []string{
|
||||||
|
"/v1/chat/completions",
|
||||||
|
"/v1/completions",
|
||||||
|
"/v1/messages",
|
||||||
|
"/v1/responses",
|
||||||
|
"/v1beta/models/",
|
||||||
|
"/api/provider/",
|
||||||
|
}
|
||||||
|
|
||||||
const skipGinLogKey = "__gin_skip_request_logging__"
|
const skipGinLogKey = "__gin_skip_request_logging__"
|
||||||
|
|
||||||
// GinLogrusLogger returns a Gin middleware handler that logs HTTP requests and responses
|
// GinLogrusLogger returns a Gin middleware handler that logs HTTP requests and responses
|
||||||
// using logrus. It captures request details including method, path, status code, latency,
|
// using logrus. It captures request details including method, path, status code, latency,
|
||||||
// client IP, and any error messages, formatted with request ID for correlation.
|
// client IP, and any error messages. Request ID is only added for AI API requests.
|
||||||
//
|
//
|
||||||
// Output format: [2025-12-23 20:14:10] [info ] [a1b2c3d4] 200 | 23.559s | 144.34.236.116 | POST "/v1/messages?beta=true"
|
// Output format (AI API): [2025-12-23 20:14:10] [info ] | a1b2c3d4 | 200 | 23.559s | ...
|
||||||
|
// Output format (others): [2025-12-23 20:14:10] [info ] | -------- | 200 | 23.559s | ...
|
||||||
//
|
//
|
||||||
// Returns:
|
// Returns:
|
||||||
// - gin.HandlerFunc: A middleware handler for request logging
|
// - gin.HandlerFunc: A middleware handler for request logging
|
||||||
func GinLogrusLogger() gin.HandlerFunc {
|
func GinLogrusLogger() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
requestID := GenerateRequestID()
|
|
||||||
SetGinRequestID(c, requestID)
|
|
||||||
|
|
||||||
ctx := WithRequestID(c.Request.Context(), requestID)
|
|
||||||
c.Request = c.Request.WithContext(ctx)
|
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
path := c.Request.URL.Path
|
path := c.Request.URL.Path
|
||||||
raw := util.MaskSensitiveQuery(c.Request.URL.RawQuery)
|
raw := util.MaskSensitiveQuery(c.Request.URL.RawQuery)
|
||||||
|
|
||||||
|
// Only generate request ID for AI API paths
|
||||||
|
var requestID string
|
||||||
|
if isAIAPIPath(path) {
|
||||||
|
requestID = GenerateRequestID()
|
||||||
|
SetGinRequestID(c, requestID)
|
||||||
|
ctx := WithRequestID(c.Request.Context(), requestID)
|
||||||
|
c.Request = c.Request.WithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
c.Next()
|
c.Next()
|
||||||
|
|
||||||
if shouldSkipGinRequestLogging(c) {
|
if shouldSkipGinRequestLogging(c) {
|
||||||
@@ -63,7 +78,13 @@ func GinLogrusLogger() gin.HandlerFunc {
|
|||||||
logLine = logLine + " | " + errorMessage
|
logLine = logLine + " | " + errorMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
entry := log.WithField("request_id", requestID)
|
var entry *log.Entry
|
||||||
|
if requestID != "" {
|
||||||
|
entry = log.WithField("request_id", requestID)
|
||||||
|
} else {
|
||||||
|
entry = log.WithField("request_id", "--------")
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case statusCode >= http.StatusInternalServerError:
|
case statusCode >= http.StatusInternalServerError:
|
||||||
entry.Error(logLine)
|
entry.Error(logLine)
|
||||||
@@ -75,6 +96,16 @@ func GinLogrusLogger() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isAIAPIPath checks if the given path is an AI API endpoint that should have request ID tracking.
|
||||||
|
func isAIAPIPath(path string) bool {
|
||||||
|
for _, prefix := range aiAPIPrefixes {
|
||||||
|
if strings.HasPrefix(path, prefix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// GinLogrusRecovery returns a Gin middleware handler that recovers from panics and logs
|
// GinLogrusRecovery returns a Gin middleware handler that recovers from panics and logs
|
||||||
// them using logrus. When a panic occurs, it captures the panic value, stack trace,
|
// them using logrus. When a panic occurs, it captures the panic value, stack trace,
|
||||||
// and request path, then returns a 500 Internal Server Error response to the client.
|
// and request path, then returns a 500 Internal Server Error response to the client.
|
||||||
|
|||||||
Reference in New Issue
Block a user