feat: add support for request ID tracking across services
- Implemented request ID handling in various services and handlers to improve traceability of requests. - Added new AuthOptions endpoint to expose WxWork and OIDC configuration options. - Updated message and event logging to include request ID for better debugging. - Enhanced login form to dynamically show available authentication options based on server configuration. - Introduced utility functions for normalizing and ensuring valid request IDs. - Updated tests to verify request ID functionality in message sending and event logging.
This commit is contained in:
@@ -18,3 +18,8 @@ type LoginResponse struct {
|
||||
Permissions []string `json:"permissions"`
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
type AuthOptionsResponse struct {
|
||||
WxWorkEnabled bool `json:"wxworkEnabled"`
|
||||
OIDCEnabled bool `json:"oidcEnabled"`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import "cs-agent/internal/pkg/enums"
|
||||
type MessageResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
ClientMsgID string `json:"clientMsgId,omitempty"`
|
||||
SenderType enums.IMSenderType `json:"senderType"`
|
||||
SenderID int64 `json:"senderId"`
|
||||
|
||||
@@ -44,6 +44,7 @@ type AgentRunLogResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversationId"`
|
||||
MessageID int64 `json:"messageId"`
|
||||
RequestID string `json:"requestId"`
|
||||
AIAgentID int64 `json:"aiAgentId"`
|
||||
AIConfigID int64 `json:"aiConfigId"`
|
||||
UserMessage string `json:"userMessage"`
|
||||
|
||||
@@ -3,6 +3,7 @@ package httpx
|
||||
import (
|
||||
"cs-agent/internal/pkg/httpx/params"
|
||||
"cs-agent/internal/pkg/openidentity"
|
||||
"cs-agent/internal/pkg/tracex"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mlogclub/simple/common/strs"
|
||||
@@ -31,3 +32,15 @@ func GetChannelID(ctx *gin.Context) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetRequestID(ctx *gin.Context) string {
|
||||
if ctx == nil {
|
||||
return ""
|
||||
}
|
||||
if value, ok := ctx.Get(tracex.GinRequestIDKey); ok {
|
||||
if requestID, ok := value.(string); ok {
|
||||
return tracex.NormalizeRequestID(requestID)
|
||||
}
|
||||
}
|
||||
return tracex.NormalizeRequestID(ctx.GetHeader(tracex.RequestIDHeader))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
RequestIDHeader = "X-Request-Id"
|
||||
GinRequestIDKey = "requestId"
|
||||
)
|
||||
|
||||
type requestIDContextKey struct{}
|
||||
|
||||
func NormalizeRequestID(value string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || len(value) > 128 {
|
||||
return ""
|
||||
}
|
||||
for _, r := range value {
|
||||
if r < 33 || r > 126 {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func EnsureRequestID(value string) string {
|
||||
if normalized := NormalizeRequestID(value); normalized != "" {
|
||||
return normalized
|
||||
}
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return ""
|
||||
}
|
||||
return hex.EncodeToString(b[:])
|
||||
}
|
||||
|
||||
func ContextWithRequestID(ctx context.Context, requestID string) context.Context {
|
||||
requestID = NormalizeRequestID(requestID)
|
||||
if requestID == "" {
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, requestIDContextKey{}, requestID)
|
||||
}
|
||||
|
||||
func RequestIDFromContext(ctx context.Context) string {
|
||||
if ctx == nil {
|
||||
return ""
|
||||
}
|
||||
if value, ok := ctx.Value(requestIDContextKey{}).(string); ok {
|
||||
return NormalizeRequestID(value)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package tracex
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNormalizeRequestID(t *testing.T) {
|
||||
if got := NormalizeRequestID(" trace-123 "); got != "trace-123" {
|
||||
t.Fatalf("NormalizeRequestID()=%q want %q", got, "trace-123")
|
||||
}
|
||||
if got := NormalizeRequestID("bad\nid"); got != "" {
|
||||
t.Fatalf("NormalizeRequestID()=%q want empty", got)
|
||||
}
|
||||
if got := NormalizeRequestID(""); got != "" {
|
||||
t.Fatalf("NormalizeRequestID()=%q want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureRequestID(t *testing.T) {
|
||||
if got := EnsureRequestID("trace-123"); got != "trace-123" {
|
||||
t.Fatalf("EnsureRequestID(existing)=%q want %q", got, "trace-123")
|
||||
}
|
||||
if got := EnsureRequestID(""); got == "" {
|
||||
t.Fatalf("EnsureRequestID(empty) should generate a value")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user