fix(ccm): log assigned credential for each distinct model per session

This commit is contained in:
世界
2026-03-21 11:07:43 +08:00
parent 29b901a8b3
commit f172a575b7
2 changed files with 40 additions and 6 deletions
+22
View File
@@ -5,6 +5,8 @@ import (
"encoding/json"
"net/http"
"strings"
"sync"
"time"
"github.com/sagernet/sing-box/adapter"
boxService "github.com/sagernet/sing-box/adapter/service"
@@ -163,10 +165,29 @@ type Service struct {
allCredentials []Credential
userConfigMap map[string]*option.CCMUser
sessionModelAccess sync.Mutex
sessionModels map[sessionModelKey]time.Time
statusSubscriber *observable.Subscriber[struct{}]
statusObserver *observable.Observer[struct{}]
}
type sessionModelKey struct {
sessionID string
model string
}
func (s *Service) cleanSessionModels() {
now := time.Now()
s.sessionModelAccess.Lock()
for key, createdAt := range s.sessionModels {
if now.Sub(createdAt) > sessionExpiry {
delete(s.sessionModels, key)
}
}
s.sessionModelAccess.Unlock()
}
func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.CCMServiceOptions) (adapter.Service, error) {
initCCMUserAgent(logger)
@@ -212,6 +233,7 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
Listen: options.ListenOptions,
}),
userManager: userManager,
sessionModels: make(map[sessionModelKey]time.Time),
statusSubscriber: statusSubscriber,
statusObserver: observable.NewObserver[struct{}](statusSubscriber, 8),
}
+18 -6
View File
@@ -218,6 +218,7 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
provider.pollIfStale()
s.cleanSessionModels()
anthropicBetaHeader := r.Header.Get("anthropic-beta")
if isFastModeRequest(anthropicBetaHeader) {
@@ -235,7 +236,22 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
writeNonRetryableCredentialError(w, r, unavailableCredentialMessage(provider, err.Error()))
return
}
if isNew {
modelDisplay := requestModel
if requestModel != "" && isExtendedContextRequest(anthropicBetaHeader) {
modelDisplay += "[1m]"
}
isNewModel := false
if sessionID != "" && modelDisplay != "" {
key := sessionModelKey{sessionID, modelDisplay}
s.sessionModelAccess.Lock()
_, exists := s.sessionModels[key]
if !exists {
s.sessionModels[key] = time.Now()
isNewModel = true
}
s.sessionModelAccess.Unlock()
}
if isNew || isNewModel {
logParts := []any{"assigned credential ", selectedCredential.tagName()}
if sessionID != "" {
logParts = append(logParts, " for session ", sessionID)
@@ -243,11 +259,7 @@ func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if username != "" {
logParts = append(logParts, " by user ", username)
}
if requestModel != "" {
modelDisplay := requestModel
if isExtendedContextRequest(anthropicBetaHeader) {
modelDisplay += "[1m]"
}
if modelDisplay != "" {
logParts = append(logParts, ", model=", modelDisplay)
}
s.logger.DebugContext(ctx, logParts...)