fix(metrics): 补齐媒体结果存储读取与兼容响应指标
增加对象存储 GET、结果 URL 签名和同步 Base64 限流指标,使生产轮询可直接验证零对象下载,并区分签名失败、容量等待超时和 20MiB 超限。\n\n验证:API 全量 go test、go vet、gofmt 与 git diff --check。
This commit is contained in:
@@ -1315,7 +1315,7 @@ func (s *Server) createTask(kind string, compatible bool) http.Handler {
|
||||
runCtx, cancelRun := s.requestExecutionContext(r)
|
||||
defer cancelRun()
|
||||
if responsePlan.compatibleMode {
|
||||
writeProtocolCompatibleTaskResponse(runCtx, w, r, s.runner, kind, model, targetProtocol, task, user, responsePlan.streamMode, streamIncludeUsage(body))
|
||||
writeProtocolCompatibleTaskResponse(runCtx, w, r, s.runner, kind, model, targetProtocol, task, user, responsePlan.streamMode, streamIncludeUsage(body), s.billingMetrics)
|
||||
return
|
||||
}
|
||||
result, runErr := s.runner.Execute(runCtx, task, user)
|
||||
@@ -1474,10 +1474,10 @@ type taskExecutor interface {
|
||||
}
|
||||
|
||||
func writeCompatibleTaskResponse(runCtx context.Context, w http.ResponseWriter, r *http.Request, executor taskExecutor, kind string, model string, task store.GatewayTask, user *auth.User, streamMode bool, includeUsage bool) {
|
||||
writeProtocolCompatibleTaskResponse(runCtx, w, r, executor, kind, model, "", task, user, streamMode, includeUsage)
|
||||
writeProtocolCompatibleTaskResponse(runCtx, w, r, executor, kind, model, "", task, user, streamMode, includeUsage, nil)
|
||||
}
|
||||
|
||||
func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.ResponseWriter, r *http.Request, executor taskExecutor, kind string, model string, targetProtocol string, task store.GatewayTask, user *auth.User, streamMode bool, includeUsage bool) {
|
||||
func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.ResponseWriter, r *http.Request, executor taskExecutor, kind string, model string, targetProtocol string, task store.GatewayTask, user *auth.User, streamMode bool, includeUsage bool, base64Observer interface{ ObserveSynchronousBase64(string) }) {
|
||||
if targetProtocol == "" || gatewayAPIV1Request(r) {
|
||||
w.Header().Set("X-Gateway-Task-Id", task.ID)
|
||||
}
|
||||
@@ -1557,12 +1557,16 @@ func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.Response
|
||||
|
||||
releaseInlineResponse, limitErr := acquireSynchronousInlineResponseSlot(runCtx, kind, task.Request)
|
||||
if limitErr != nil {
|
||||
observeSynchronousBase64(base64Observer, "capacity_timeout")
|
||||
writeProtocolError(w, targetProtocol, statusFromRunError(limitErr), runErrorMessage(limitErr), runErrorDetails(limitErr), runErrorCode(limitErr))
|
||||
return
|
||||
}
|
||||
defer releaseInlineResponse()
|
||||
result, runErr := executor.Execute(runCtx, task, user)
|
||||
if runErr != nil {
|
||||
if clients.ErrorCode(runErr) == "response_format_too_large" {
|
||||
observeSynchronousBase64(base64Observer, "too_large")
|
||||
}
|
||||
if !requestStillConnected(r) {
|
||||
return
|
||||
}
|
||||
@@ -1580,6 +1584,7 @@ func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.Response
|
||||
if synchronousInlineResponseRequested(kind, task.Request) {
|
||||
rawBytes := inlineMediaDecodedSize(result.Output)
|
||||
if rawBytes > maxSynchronousInlineResponseBytes {
|
||||
observeSynchronousBase64(base64Observer, "too_large")
|
||||
writeProtocolError(w, targetProtocol, http.StatusRequestEntityTooLarge, "synchronous Base64 response exceeds the 20 MiB limit", map[string]any{
|
||||
"task_id": result.Task.ID,
|
||||
"query_url": "/api/v1/ai/result/" + result.Task.ID,
|
||||
@@ -1590,6 +1595,7 @@ func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.Response
|
||||
return
|
||||
}
|
||||
if rawBytes > 0 {
|
||||
observeSynchronousBase64(base64Observer, "success")
|
||||
w.Header().Set("X-Gateway-Response-Format", "b64_json")
|
||||
} else {
|
||||
w.Header().Set("X-Gateway-Response-Format", "url")
|
||||
@@ -1620,6 +1626,12 @@ func acquireSynchronousInlineResponseSlot(ctx context.Context, kind string, requ
|
||||
}
|
||||
}
|
||||
|
||||
func observeSynchronousBase64(observer interface{ ObserveSynchronousBase64(string) }, outcome string) {
|
||||
if observer != nil {
|
||||
observer.ObserveSynchronousBase64(outcome)
|
||||
}
|
||||
}
|
||||
|
||||
func synchronousInlineResponseRequested(kind string, request map[string]any) bool {
|
||||
if !mediaResultKind(kind) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user