fix: 对齐 Claude Code 2.1.88 源码指纹
- 1P event_logging/batch 添加 OAuth Bearer auth header - DD hostname 改为固定 "claude-code"(与真实 CLI 一致) - 事件名对齐真实 CLI: tengu_api_query/tengu_api_success/tengu_api_error/tengu_tool_use_success - DD header 大小写改为 DD-API-KEY - ResponseHeaderTimeout 300s → 600s(与真实 CLI 10min 超时对齐)
This commit is contained in:
parent
2f817dd248
commit
b285fb7b2f
@ -322,7 +322,7 @@ func buildEvent(eventName string, session *sessionState, model, betas string, ex
|
||||
|
||||
var httpClient = &http.Client{Timeout: telemetryTimeout}
|
||||
|
||||
func sendTelemetryEvents(events []eventWrapper, session *sessionState) {
|
||||
func sendTelemetryEvents(events []eventWrapper, session *sessionState, authToken string) {
|
||||
if len(events) == 0 {
|
||||
return
|
||||
}
|
||||
@ -341,6 +341,9 @@ func sendTelemetryEvents(events []eventWrapper, session *sessionState) {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "claude-code/"+claude.DefaultCLIVersion)
|
||||
req.Header.Set("x-service-name", "claude-code")
|
||||
if authToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+authToken)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
@ -383,7 +386,7 @@ func sendDatadogLog(eventName string, session *sessionState, model string) {
|
||||
"ddtags": fmt.Sprintf("event:%s,arch:%s,client_type:cli,model:%s,platform:darwin,user_type:external,version:%s,version_base:%s", eventName, hostID.Arch, model, claude.DefaultCLIVersion, claude.DefaultCLIVersion),
|
||||
"message": eventName,
|
||||
"service": "claude-code",
|
||||
"hostname": hostID.Hostname,
|
||||
"hostname": "claude-code",
|
||||
"env": "external",
|
||||
"model": model,
|
||||
"session_id": session.SessionID,
|
||||
@ -415,7 +418,7 @@ func sendDatadogLog(eventName string, session *sessionState, model string) {
|
||||
req.Header.Set("Accept", "application/json, text/plain, */*")
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "axios/1.13.6")
|
||||
req.Header.Set("dd-api-key", ddAPIKey)
|
||||
req.Header.Set("DD-API-KEY", ddAPIKey)
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
@ -429,9 +432,10 @@ func sendDatadogLog(eventName string, session *sessionState, model string) {
|
||||
// EmitPreRequest fires pre-request telemetry events for a /v1/messages request.
|
||||
// accountSeed should be a stable identifier for the account (e.g. account ID or OAuth token suffix).
|
||||
// authHeader is the Authorization header value (used for device ID derivation).
|
||||
// authToken is the raw OAuth token (without "Bearer " prefix) for 1P auth.
|
||||
// model is the model name from the request body (e.g. "claude-sonnet-4-6").
|
||||
// betaHeader is the anthropic-beta header value.
|
||||
func EmitPreRequest(accountSeed, authHeader, model, betaHeader string) {
|
||||
func EmitPreRequest(accountSeed, authHeader, authToken, model, betaHeader string) {
|
||||
authSuffix := authHeader
|
||||
if len(authSuffix) > 16 {
|
||||
authSuffix = authSuffix[len(authSuffix)-16:]
|
||||
@ -479,29 +483,28 @@ func EmitPreRequest(accountSeed, authHeader, model, betaHeader string) {
|
||||
}
|
||||
|
||||
session.RipgrepReported = true
|
||||
go sendTelemetryEvents(batch1, session)
|
||||
go sendTelemetryEvents(batch1, session, authToken)
|
||||
go sendDatadogLog("tengu_started", session, model)
|
||||
go sendDatadogLog("tengu_init", session, model)
|
||||
|
||||
// Delayed batch (~25-35s later, matches real CLI timing)
|
||||
go func() {
|
||||
time.Sleep(time.Duration(25000+rand.Intn(10000)) * time.Millisecond)
|
||||
batch2 := []eventWrapper{
|
||||
sendTelemetryEvents([]eventWrapper{
|
||||
buildEvent("tengu_session_init", session, model, betas, nil, ""),
|
||||
buildEvent("tengu_context_loaded", session, model, betas, nil, ""),
|
||||
}
|
||||
sendTelemetryEvents(batch2, session)
|
||||
}, session, authToken)
|
||||
}()
|
||||
}
|
||||
|
||||
// Every request: request_started
|
||||
// Every request: tengu_api_query (real CLI event name)
|
||||
go sendTelemetryEvents([]eventWrapper{
|
||||
buildEvent("tengu_api_request_started", session, model, betas, nil, ""),
|
||||
}, session)
|
||||
buildEvent("tengu_api_query", session, model, betas, nil, ""),
|
||||
}, session, authToken)
|
||||
}
|
||||
|
||||
// EmitPostRequest fires post-request telemetry events after upstream response.
|
||||
func EmitPostRequest(accountSeed, authHeader, model, betaHeader string, statusCode int) {
|
||||
func EmitPostRequest(accountSeed, authHeader, authToken, model, betaHeader string, statusCode int) {
|
||||
authSuffix := authHeader
|
||||
if len(authSuffix) > 16 {
|
||||
authSuffix = authSuffix[len(authSuffix)-16:]
|
||||
@ -517,15 +520,14 @@ func EmitPostRequest(accountSeed, authHeader, model, betaHeader string, statusCo
|
||||
betas = claude.DefaultBetaHeader
|
||||
}
|
||||
|
||||
events := []eventWrapper{
|
||||
buildEvent("tengu_api_request_completed", session, model, betas, nil, ""),
|
||||
buildEvent("tengu_conversation_turn_completed", session, model, betas, nil, ""),
|
||||
}
|
||||
go sendTelemetryEvents(events, session)
|
||||
go sendDatadogLog("tengu_api_request_completed", session, model)
|
||||
|
||||
// Error telemetry
|
||||
if statusCode >= 400 && rand.Float64() < 0.5 {
|
||||
// Real CLI uses tengu_api_success on success, tengu_api_error on failure
|
||||
if statusCode < 400 {
|
||||
events := []eventWrapper{
|
||||
buildEvent("tengu_api_success", session, model, betas, nil, ""),
|
||||
}
|
||||
go sendTelemetryEvents(events, session, authToken)
|
||||
go sendDatadogLog("tengu_api_success", session, model)
|
||||
} else {
|
||||
var errMsg string
|
||||
switch {
|
||||
case statusCode == 429:
|
||||
@ -537,12 +539,13 @@ func EmitPostRequest(accountSeed, authHeader, model, betaHeader string, statusCo
|
||||
default:
|
||||
errMsg = "client_error"
|
||||
}
|
||||
errEvent := buildEvent("tengu_api_request_error", session, model, betas, map[string]any{
|
||||
errEvent := buildEvent("tengu_api_error", session, model, betas, map[string]any{
|
||||
"error_type": "TelemetrySafeError",
|
||||
"error_code": statusCode,
|
||||
"error_message": errMsg,
|
||||
}, "")
|
||||
go sendTelemetryEvents([]eventWrapper{errEvent}, session)
|
||||
go sendTelemetryEvents([]eventWrapper{errEvent}, session, authToken)
|
||||
go sendDatadogLog("tengu_api_error", session, model)
|
||||
}
|
||||
|
||||
// Random tool_use event (30% probability, 2-7s delay)
|
||||
@ -550,8 +553,8 @@ func EmitPostRequest(accountSeed, authHeader, model, betaHeader string, statusCo
|
||||
go func() {
|
||||
time.Sleep(time.Duration(2000+rand.Intn(5000)) * time.Millisecond)
|
||||
sendTelemetryEvents([]eventWrapper{
|
||||
buildEvent("tengu_tool_use_completed", session, model, betas, nil, ""),
|
||||
}, session)
|
||||
buildEvent("tengu_tool_use_success", session, model, betas, nil, ""),
|
||||
}, session, authToken)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ const (
|
||||
defaultIdleConnTimeout = 90 * time.Second
|
||||
// defaultResponseHeaderTimeout: 默认等待响应头超时时间(5分钟)
|
||||
// LLM 请求可能排队较久,需要较长超时
|
||||
defaultResponseHeaderTimeout = 300 * time.Second
|
||||
defaultResponseHeaderTimeout = 600 * time.Second
|
||||
// defaultMaxUpstreamClients: 默认最大客户端缓存数量
|
||||
// 超出后会淘汰最久未使用的客户端
|
||||
defaultMaxUpstreamClients = 5000
|
||||
|
||||
@ -4228,10 +4228,11 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *A
|
||||
// 真实 CLI 在首次 messages 请求前 fire-and-forget 调用此端点。
|
||||
if tokenType == "oauth" && token != "" {
|
||||
TriggerBootstrapIfNeeded(account.ID, token)
|
||||
// OTEL telemetry: emit pre-request events (tengu_started, tengu_api_request_started etc.)
|
||||
// OTEL telemetry: emit pre-request events (tengu_started, tengu_api_query etc.)
|
||||
go telemetry.EmitPreRequest(
|
||||
fmt.Sprintf("%d", account.ID),
|
||||
token,
|
||||
token,
|
||||
reqModel,
|
||||
getHeaderRaw(c.Request.Header, "anthropic-beta"),
|
||||
)
|
||||
@ -4657,6 +4658,7 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *A
|
||||
go telemetry.EmitPostRequest(
|
||||
fmt.Sprintf("%d", account.ID),
|
||||
token,
|
||||
token,
|
||||
reqModel,
|
||||
getHeaderRaw(c.Request.Header, "anthropic-beta"),
|
||||
resp.StatusCode,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user