- 修复depguard错误:为ops service文件添加redis导入例外 - 修复errcheck错误:添加错误检查和类型断言检查 - 修复gofmt错误:格式化代码 - 修复ineffassign错误:移除无效的idx++赋值 - 修复staticcheck错误:合并条件赋值 - 修复unused错误:移除未使用的字段和函数 - ops_cleanup_service.go: entryID字段 - ops_retry.go: status字段 - ops_upstream_context.go: getOpsUpstreamErrors函数
95 lines
2.6 KiB
Go
95 lines
2.6 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// Gin context keys used by Ops error logger for capturing upstream error details.
|
|
// These keys are set by gateway services and consumed by handler/ops_error_logger.go.
|
|
const (
|
|
OpsUpstreamStatusCodeKey = "ops_upstream_status_code"
|
|
OpsUpstreamErrorMessageKey = "ops_upstream_error_message"
|
|
OpsUpstreamErrorDetailKey = "ops_upstream_error_detail"
|
|
OpsUpstreamErrorsKey = "ops_upstream_errors"
|
|
)
|
|
|
|
func setOpsUpstreamError(c *gin.Context, upstreamStatusCode int, upstreamMessage, upstreamDetail string) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
if upstreamStatusCode > 0 {
|
|
c.Set(OpsUpstreamStatusCodeKey, upstreamStatusCode)
|
|
}
|
|
if msg := strings.TrimSpace(upstreamMessage); msg != "" {
|
|
c.Set(OpsUpstreamErrorMessageKey, msg)
|
|
}
|
|
if detail := strings.TrimSpace(upstreamDetail); detail != "" {
|
|
c.Set(OpsUpstreamErrorDetailKey, detail)
|
|
}
|
|
}
|
|
|
|
// OpsUpstreamErrorEvent describes one upstream error attempt during a single gateway request.
|
|
// It is stored in ops_error_logs.upstream_errors as a JSON array.
|
|
type OpsUpstreamErrorEvent struct {
|
|
AtUnixMs int64 `json:"at_unix_ms,omitempty"`
|
|
|
|
// Context
|
|
Platform string `json:"platform,omitempty"`
|
|
AccountID int64 `json:"account_id,omitempty"`
|
|
|
|
// Outcome
|
|
UpstreamStatusCode int `json:"upstream_status_code,omitempty"`
|
|
UpstreamRequestID string `json:"upstream_request_id,omitempty"`
|
|
|
|
// Kind: http_error | request_error | retry_exhausted | failover
|
|
Kind string `json:"kind,omitempty"`
|
|
|
|
Message string `json:"message,omitempty"`
|
|
Detail string `json:"detail,omitempty"`
|
|
}
|
|
|
|
func appendOpsUpstreamError(c *gin.Context, ev OpsUpstreamErrorEvent) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
if ev.AtUnixMs <= 0 {
|
|
ev.AtUnixMs = time.Now().UnixMilli()
|
|
}
|
|
ev.Platform = strings.TrimSpace(ev.Platform)
|
|
ev.UpstreamRequestID = strings.TrimSpace(ev.UpstreamRequestID)
|
|
ev.Kind = strings.TrimSpace(ev.Kind)
|
|
ev.Message = strings.TrimSpace(ev.Message)
|
|
ev.Detail = strings.TrimSpace(ev.Detail)
|
|
if ev.Message != "" {
|
|
ev.Message = sanitizeUpstreamErrorMessage(ev.Message)
|
|
}
|
|
|
|
var existing []*OpsUpstreamErrorEvent
|
|
if v, ok := c.Get(OpsUpstreamErrorsKey); ok {
|
|
if arr, ok := v.([]*OpsUpstreamErrorEvent); ok {
|
|
existing = arr
|
|
}
|
|
}
|
|
|
|
evCopy := ev
|
|
existing = append(existing, &evCopy)
|
|
c.Set(OpsUpstreamErrorsKey, existing)
|
|
}
|
|
|
|
func marshalOpsUpstreamErrors(events []*OpsUpstreamErrorEvent) *string {
|
|
if len(events) == 0 {
|
|
return nil
|
|
}
|
|
// Ensure we always store a valid JSON value.
|
|
raw, err := json.Marshal(events)
|
|
if err != nil || len(raw) == 0 {
|
|
return nil
|
|
}
|
|
s := string(raw)
|
|
return &s
|
|
}
|