fix: 修复错误透传规则 skip_monitoring 未生效的问题
- ops_error_logger: status < 400 分支增加 OpsSkipPassthroughKey 检查 - ops_upstream_context: 新增 checkSkipMonitoringForUpstreamEvent,中间重试/故障转移事件也能触发跳过标记 - gateway_handler/openai_gateway_handler/gemini_v1beta_handler: handleFailoverExhausted 匹配规则后设置 OpsSkipPassthroughKey - antigravity_gateway_service: writeMappedClaudeError 增加 applyErrorPassthroughRule 调用
This commit is contained in:
@@ -971,6 +971,10 @@ func (h *GatewayHandler) handleFailoverExhausted(c *gin.Context, failoverErr *se
|
|||||||
msg = *rule.CustomMessage
|
msg = *rule.CustomMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rule.SkipMonitoring {
|
||||||
|
c.Set(service.OpsSkipPassthroughKey, true)
|
||||||
|
}
|
||||||
|
|
||||||
h.handleStreamingAwareError(c, respCode, "upstream_error", msg, streamStarted)
|
h.handleStreamingAwareError(c, respCode, "upstream_error", msg, streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,6 +554,10 @@ func (h *GatewayHandler) handleGeminiFailoverExhausted(c *gin.Context, failoverE
|
|||||||
msg = *rule.CustomMessage
|
msg = *rule.CustomMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rule.SkipMonitoring {
|
||||||
|
c.Set(service.OpsSkipPassthroughKey, true)
|
||||||
|
}
|
||||||
|
|
||||||
googleError(c, respCode, msg)
|
googleError(c, respCode, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,6 +354,10 @@ func (h *OpenAIGatewayHandler) handleFailoverExhausted(c *gin.Context, failoverE
|
|||||||
msg = *rule.CustomMessage
|
msg = *rule.CustomMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rule.SkipMonitoring {
|
||||||
|
c.Set(service.OpsSkipPassthroughKey, true)
|
||||||
|
}
|
||||||
|
|
||||||
h.handleStreamingAwareError(c, respCode, "upstream_error", msg, streamStarted)
|
h.handleStreamingAwareError(c, respCode, "upstream_error", msg, streamStarted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,6 +537,13 @@ func OpsErrorLoggerMiddleware(ops *service.OpsService) gin.HandlerFunc {
|
|||||||
// Store request headers/body only when an upstream error occurred to keep overhead minimal.
|
// Store request headers/body only when an upstream error occurred to keep overhead minimal.
|
||||||
entry.RequestHeadersJSON = extractOpsRetryRequestHeaders(c)
|
entry.RequestHeadersJSON = extractOpsRetryRequestHeaders(c)
|
||||||
|
|
||||||
|
// Skip logging if a passthrough rule with skip_monitoring=true matched.
|
||||||
|
if v, ok := c.Get(service.OpsSkipPassthroughKey); ok {
|
||||||
|
if skip, _ := v.(bool); skip {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enqueueOpsErrorLog(ops, entry, requestBody)
|
enqueueOpsErrorLog(ops, entry, requestBody)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3251,6 +3251,21 @@ func (s *AntigravityGatewayService) writeMappedClaudeError(c *gin.Context, accou
|
|||||||
log.Printf("[antigravity-Forward] upstream_error status=%d body=%s", upstreamStatus, truncateForLog(body, maxBytes))
|
log.Printf("[antigravity-Forward] upstream_error status=%d body=%s", upstreamStatus, truncateForLog(body, maxBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查错误透传规则
|
||||||
|
if ptStatus, ptErrType, ptErrMsg, matched := applyErrorPassthroughRule(
|
||||||
|
c, account.Platform, upstreamStatus, body,
|
||||||
|
0, "", "",
|
||||||
|
); matched {
|
||||||
|
c.JSON(ptStatus, gin.H{
|
||||||
|
"type": "error",
|
||||||
|
"error": gin.H{"type": ptErrType, "message": ptErrMsg},
|
||||||
|
})
|
||||||
|
if upstreamMsg == "" {
|
||||||
|
return fmt.Errorf("upstream error: %d", upstreamStatus)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("upstream error: %d message=%s", upstreamStatus, upstreamMsg)
|
||||||
|
}
|
||||||
|
|
||||||
var statusCode int
|
var statusCode int
|
||||||
var errType, errMsg string
|
var errType, errMsg string
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,37 @@ func appendOpsUpstreamError(c *gin.Context, ev OpsUpstreamErrorEvent) {
|
|||||||
evCopy := ev
|
evCopy := ev
|
||||||
existing = append(existing, &evCopy)
|
existing = append(existing, &evCopy)
|
||||||
c.Set(OpsUpstreamErrorsKey, existing)
|
c.Set(OpsUpstreamErrorsKey, existing)
|
||||||
|
|
||||||
|
checkSkipMonitoringForUpstreamEvent(c, &evCopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkSkipMonitoringForUpstreamEvent checks whether the upstream error event
|
||||||
|
// matches a passthrough rule with skip_monitoring=true and, if so, sets the
|
||||||
|
// OpsSkipPassthroughKey on the context. This ensures intermediate retry /
|
||||||
|
// failover errors (which never go through the final applyErrorPassthroughRule
|
||||||
|
// path) can still suppress ops_error_logs recording.
|
||||||
|
func checkSkipMonitoringForUpstreamEvent(c *gin.Context, ev *OpsUpstreamErrorEvent) {
|
||||||
|
if ev.UpstreamStatusCode == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := getBoundErrorPassthroughService(c)
|
||||||
|
if svc == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the best available body representation for keyword matching.
|
||||||
|
// Even when body is empty, MatchRule can still match rules that only
|
||||||
|
// specify ErrorCodes (no Keywords), so we always call it.
|
||||||
|
body := ev.Detail
|
||||||
|
if body == "" {
|
||||||
|
body = ev.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
rule := svc.MatchRule(ev.Platform, ev.UpstreamStatusCode, []byte(body))
|
||||||
|
if rule != nil && rule.SkipMonitoring {
|
||||||
|
c.Set(OpsSkipPassthroughKey, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalOpsUpstreamErrors(events []*OpsUpstreamErrorEvent) *string {
|
func marshalOpsUpstreamErrors(events []*OpsUpstreamErrorEvent) *string {
|
||||||
|
|||||||
Reference in New Issue
Block a user