ops_port.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. package service
  2. import (
  3. "context"
  4. "time"
  5. )
  6. type OpsRepository interface {
  7. InsertErrorLog(ctx context.Context, input *OpsInsertErrorLogInput) (int64, error)
  8. BatchInsertErrorLogs(ctx context.Context, inputs []*OpsInsertErrorLogInput) (int64, error)
  9. ListErrorLogs(ctx context.Context, filter *OpsErrorLogFilter) (*OpsErrorLogList, error)
  10. GetErrorLogByID(ctx context.Context, id int64) (*OpsErrorLogDetail, error)
  11. ListRequestDetails(ctx context.Context, filter *OpsRequestDetailFilter) ([]*OpsRequestDetail, int64, error)
  12. BatchInsertSystemLogs(ctx context.Context, inputs []*OpsInsertSystemLogInput) (int64, error)
  13. ListSystemLogs(ctx context.Context, filter *OpsSystemLogFilter) (*OpsSystemLogList, error)
  14. DeleteSystemLogs(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error)
  15. InsertSystemLogCleanupAudit(ctx context.Context, input *OpsSystemLogCleanupAudit) error
  16. UpdateErrorResolution(ctx context.Context, errorID int64, resolved bool, resolvedByUserID *int64, resolvedAt *time.Time) error
  17. // Lightweight window stats (for realtime WS / quick sampling).
  18. GetWindowStats(ctx context.Context, filter *OpsDashboardFilter) (*OpsWindowStats, error)
  19. // Lightweight realtime traffic summary (for the Ops dashboard header card).
  20. GetRealtimeTrafficSummary(ctx context.Context, filter *OpsDashboardFilter) (*OpsRealtimeTrafficSummary, error)
  21. GetDashboardOverview(ctx context.Context, filter *OpsDashboardFilter) (*OpsDashboardOverview, error)
  22. GetThroughputTrend(ctx context.Context, filter *OpsDashboardFilter, bucketSeconds int) (*OpsThroughputTrendResponse, error)
  23. GetLatencyHistogram(ctx context.Context, filter *OpsDashboardFilter) (*OpsLatencyHistogramResponse, error)
  24. GetErrorTrend(ctx context.Context, filter *OpsDashboardFilter, bucketSeconds int) (*OpsErrorTrendResponse, error)
  25. GetErrorDistribution(ctx context.Context, filter *OpsDashboardFilter) (*OpsErrorDistributionResponse, error)
  26. GetOpenAITokenStats(ctx context.Context, filter *OpsOpenAITokenStatsFilter) (*OpsOpenAITokenStatsResponse, error)
  27. InsertSystemMetrics(ctx context.Context, input *OpsInsertSystemMetricsInput) error
  28. GetLatestSystemMetrics(ctx context.Context, windowMinutes int) (*OpsSystemMetricsSnapshot, error)
  29. UpsertJobHeartbeat(ctx context.Context, input *OpsUpsertJobHeartbeatInput) error
  30. ListJobHeartbeats(ctx context.Context) ([]*OpsJobHeartbeat, error)
  31. // Alerts (rules + events)
  32. ListAlertRules(ctx context.Context) ([]*OpsAlertRule, error)
  33. CreateAlertRule(ctx context.Context, input *OpsAlertRule) (*OpsAlertRule, error)
  34. UpdateAlertRule(ctx context.Context, input *OpsAlertRule) (*OpsAlertRule, error)
  35. DeleteAlertRule(ctx context.Context, id int64) error
  36. ListAlertEvents(ctx context.Context, filter *OpsAlertEventFilter) ([]*OpsAlertEvent, error)
  37. GetAlertEventByID(ctx context.Context, eventID int64) (*OpsAlertEvent, error)
  38. GetActiveAlertEvent(ctx context.Context, ruleID int64) (*OpsAlertEvent, error)
  39. GetLatestAlertEvent(ctx context.Context, ruleID int64) (*OpsAlertEvent, error)
  40. CreateAlertEvent(ctx context.Context, event *OpsAlertEvent) (*OpsAlertEvent, error)
  41. UpdateAlertEventStatus(ctx context.Context, eventID int64, status string, resolvedAt *time.Time) error
  42. UpdateAlertEventEmailSent(ctx context.Context, eventID int64, emailSent bool) error
  43. // Alert silences
  44. CreateAlertSilence(ctx context.Context, input *OpsAlertSilence) (*OpsAlertSilence, error)
  45. IsAlertSilenced(ctx context.Context, ruleID int64, platform string, groupID *int64, region *string, now time.Time) (bool, error)
  46. // Pre-aggregation (hourly/daily) used for long-window dashboard performance.
  47. UpsertHourlyMetrics(ctx context.Context, startTime, endTime time.Time) error
  48. UpsertDailyMetrics(ctx context.Context, startTime, endTime time.Time) error
  49. GetLatestHourlyBucketStart(ctx context.Context) (time.Time, bool, error)
  50. GetLatestDailyBucketDate(ctx context.Context) (time.Time, bool, error)
  51. }
  52. type OpsInsertErrorLogInput struct {
  53. RequestID string
  54. ClientRequestID string
  55. UserID *int64
  56. APIKeyID *int64
  57. AccountID *int64
  58. GroupID *int64
  59. ClientIP *string
  60. Platform string
  61. Model string
  62. RequestPath string
  63. Stream bool
  64. // InboundEndpoint is the normalized client-facing API endpoint path, e.g. /v1/chat/completions.
  65. InboundEndpoint string
  66. // UpstreamEndpoint is the normalized upstream endpoint path, e.g. /v1/responses.
  67. UpstreamEndpoint string
  68. // RequestedModel is the client-requested model name before mapping.
  69. RequestedModel string
  70. // UpstreamModel is the actual model sent to upstream after mapping. Empty means no mapping.
  71. UpstreamModel string
  72. // RequestType is the granular request type: 0=unknown, 1=sync, 2=stream, 3=ws_v2.
  73. // Matches service.RequestType enum semantics from usage_log.go.
  74. RequestType *int16
  75. UserAgent string
  76. ErrorPhase string
  77. ErrorType string
  78. Severity string
  79. StatusCode int
  80. IsBusinessLimited bool
  81. IsCountTokens bool // 是否为 count_tokens 请求
  82. ErrorMessage string
  83. ErrorBody string
  84. ErrorSource string
  85. ErrorOwner string
  86. UpstreamStatusCode *int
  87. UpstreamErrorMessage *string
  88. UpstreamErrorDetail *string
  89. // UpstreamErrors captures all upstream error attempts observed during handling this request.
  90. // It is populated during request processing (gin context) and sanitized+serialized by OpsService.
  91. UpstreamErrors []*OpsUpstreamErrorEvent
  92. // UpstreamErrorsJSON is the sanitized JSON string stored into ops_error_logs.upstream_errors.
  93. // It is set by OpsService.RecordError before persisting.
  94. UpstreamErrorsJSON *string
  95. AuthLatencyMs *int64
  96. RoutingLatencyMs *int64
  97. UpstreamLatencyMs *int64
  98. ResponseLatencyMs *int64
  99. TimeToFirstTokenMs *int64
  100. CreatedAt time.Time
  101. // 有效(未删除)key 报错时快照的 key 脱敏前缀(前 8 位)。
  102. // 落库快照而非读时 JOIN:key 之后被删(key 列被 tombstone 覆盖)仍保留当时前缀。
  103. APIKeyPrefix string
  104. }
  105. type OpsInsertSystemMetricsInput struct {
  106. CreatedAt time.Time
  107. WindowMinutes int
  108. Platform *string
  109. GroupID *int64
  110. SuccessCount int64
  111. ErrorCountTotal int64
  112. BusinessLimitedCount int64
  113. ErrorCountSLA int64
  114. UpstreamErrorCountExcl429529 int64
  115. Upstream429Count int64
  116. Upstream529Count int64
  117. TokenConsumed int64
  118. AccountSwitchCount int64
  119. QPS *float64
  120. TPS *float64
  121. DurationP50Ms *int
  122. DurationP90Ms *int
  123. DurationP95Ms *int
  124. DurationP99Ms *int
  125. DurationAvgMs *float64
  126. DurationMaxMs *int
  127. TTFTP50Ms *int
  128. TTFTP90Ms *int
  129. TTFTP95Ms *int
  130. TTFTP99Ms *int
  131. TTFTAvgMs *float64
  132. TTFTMaxMs *int
  133. CPUUsagePercent *float64
  134. MemoryUsedMB *int64
  135. MemoryTotalMB *int64
  136. MemoryUsagePercent *float64
  137. DBOK *bool
  138. RedisOK *bool
  139. RedisConnTotal *int
  140. RedisConnIdle *int
  141. DBConnActive *int
  142. DBConnIdle *int
  143. DBConnWaiting *int
  144. GoroutineCount *int
  145. ConcurrencyQueueDepth *int
  146. }
  147. type OpsInsertSystemLogInput struct {
  148. CreatedAt time.Time
  149. Host string
  150. Level string
  151. Component string
  152. Message string
  153. RequestID string
  154. ClientRequestID string
  155. UserID *int64
  156. APIKeyID *int64
  157. AccountID *int64
  158. Platform string
  159. Model string
  160. ExtraJSON string
  161. }
  162. type OpsSystemLogFilter struct {
  163. StartTime *time.Time
  164. EndTime *time.Time
  165. Host string
  166. Level string
  167. Component string
  168. RequestID string
  169. ClientRequestID string
  170. UserID *int64
  171. APIKeyID *int64
  172. AccountID *int64
  173. Platform string
  174. Model string
  175. Query string
  176. Page int
  177. PageSize int
  178. }
  179. type OpsSystemLogCleanupFilter struct {
  180. StartTime *time.Time
  181. EndTime *time.Time
  182. Host string
  183. Level string
  184. Component string
  185. RequestID string
  186. ClientRequestID string
  187. UserID *int64
  188. APIKeyID *int64
  189. AccountID *int64
  190. Platform string
  191. Model string
  192. Query string
  193. }
  194. type OpsSystemLogList struct {
  195. Logs []*OpsSystemLog `json:"logs"`
  196. Total int `json:"total"`
  197. Page int `json:"page"`
  198. PageSize int `json:"page_size"`
  199. }
  200. type OpsSystemLogCleanupAudit struct {
  201. CreatedAt time.Time
  202. OperatorID int64
  203. Conditions string
  204. DeletedRows int64
  205. }
  206. type OpsSystemMetricsSnapshot struct {
  207. ID int64 `json:"id"`
  208. CreatedAt time.Time `json:"created_at"`
  209. WindowMinutes int `json:"window_minutes"`
  210. CPUUsagePercent *float64 `json:"cpu_usage_percent"`
  211. MemoryUsedMB *int64 `json:"memory_used_mb"`
  212. MemoryTotalMB *int64 `json:"memory_total_mb"`
  213. MemoryUsagePercent *float64 `json:"memory_usage_percent"`
  214. DBOK *bool `json:"db_ok"`
  215. RedisOK *bool `json:"redis_ok"`
  216. // Config-derived limits (best-effort). These are not historical metrics; they help UI render "current vs max".
  217. DBMaxOpenConns *int `json:"db_max_open_conns"`
  218. RedisPoolSize *int `json:"redis_pool_size"`
  219. RedisConnTotal *int `json:"redis_conn_total"`
  220. RedisConnIdle *int `json:"redis_conn_idle"`
  221. DBConnActive *int `json:"db_conn_active"`
  222. DBConnIdle *int `json:"db_conn_idle"`
  223. DBConnWaiting *int `json:"db_conn_waiting"`
  224. GoroutineCount *int `json:"goroutine_count"`
  225. ConcurrencyQueueDepth *int `json:"concurrency_queue_depth"`
  226. AccountSwitchCount *int64 `json:"account_switch_count"`
  227. }
  228. type OpsUpsertJobHeartbeatInput struct {
  229. JobName string
  230. LastRunAt *time.Time
  231. LastSuccessAt *time.Time
  232. LastErrorAt *time.Time
  233. LastError *string
  234. LastDurationMs *int64
  235. // LastResult is an optional human-readable summary of the last successful run.
  236. LastResult *string
  237. }
  238. type OpsJobHeartbeat struct {
  239. JobName string `json:"job_name"`
  240. LastRunAt *time.Time `json:"last_run_at"`
  241. LastSuccessAt *time.Time `json:"last_success_at"`
  242. LastErrorAt *time.Time `json:"last_error_at"`
  243. LastError *string `json:"last_error"`
  244. LastDurationMs *int64 `json:"last_duration_ms"`
  245. LastResult *string `json:"last_result"`
  246. UpdatedAt time.Time `json:"updated_at"`
  247. }
  248. type OpsWindowStats struct {
  249. StartTime time.Time `json:"start_time"`
  250. EndTime time.Time `json:"end_time"`
  251. SuccessCount int64 `json:"success_count"`
  252. ErrorCountTotal int64 `json:"error_count_total"`
  253. TokenConsumed int64 `json:"token_consumed"`
  254. }