Remove ops retry controls
This commit is contained in:
parent
2eb622f2f6
commit
e009d12a10
@ -1,52 +1,18 @@
|
|||||||
/**
|
/**
|
||||||
* Admin Ops API endpoints (vNext)
|
* Admin Ops API endpoints (vNext)
|
||||||
* - Error logs list/detail + retry (client/upstream)
|
* - Error logs list/detail
|
||||||
* - Dashboard overview (raw path)
|
* - Dashboard overview (raw path)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { apiClient } from '../client'
|
import { apiClient } from '../client'
|
||||||
import type { PaginatedResponse } from '@/types'
|
import type { PaginatedResponse } from '@/types'
|
||||||
|
|
||||||
export type OpsRetryMode = 'client' | 'upstream'
|
|
||||||
export type OpsQueryMode = 'auto' | 'raw' | 'preagg'
|
export type OpsQueryMode = 'auto' | 'raw' | 'preagg'
|
||||||
|
|
||||||
export interface OpsRequestOptions {
|
export interface OpsRequestOptions {
|
||||||
signal?: AbortSignal
|
signal?: AbortSignal
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpsRetryRequest {
|
|
||||||
mode: OpsRetryMode
|
|
||||||
pinned_account_id?: number
|
|
||||||
force?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OpsRetryAttempt {
|
|
||||||
id: number
|
|
||||||
created_at: string
|
|
||||||
requested_by_user_id: number
|
|
||||||
source_error_id: number
|
|
||||||
mode: string
|
|
||||||
pinned_account_id?: number | null
|
|
||||||
pinned_account_name?: string
|
|
||||||
|
|
||||||
status: string
|
|
||||||
started_at?: string | null
|
|
||||||
finished_at?: string | null
|
|
||||||
duration_ms?: number | null
|
|
||||||
|
|
||||||
success?: boolean | null
|
|
||||||
http_status_code?: number | null
|
|
||||||
upstream_request_id?: string | null
|
|
||||||
used_account_id?: number | null
|
|
||||||
used_account_name?: string
|
|
||||||
response_preview?: string | null
|
|
||||||
response_truncated?: boolean | null
|
|
||||||
|
|
||||||
result_request_id?: string | null
|
|
||||||
result_error_id?: number | null
|
|
||||||
error_message?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OpsUpstreamErrorEvent = {
|
export type OpsUpstreamErrorEvent = {
|
||||||
at_unix_ms?: number
|
at_unix_ms?: number
|
||||||
platform?: string
|
platform?: string
|
||||||
@ -54,33 +20,11 @@ export type OpsUpstreamErrorEvent = {
|
|||||||
account_name?: string
|
account_name?: string
|
||||||
upstream_status_code?: number
|
upstream_status_code?: number
|
||||||
upstream_request_id?: string
|
upstream_request_id?: string
|
||||||
upstream_request_body?: string
|
|
||||||
kind?: string
|
kind?: string
|
||||||
message?: string
|
message?: string
|
||||||
detail?: string
|
detail?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpsRetryResult {
|
|
||||||
attempt_id: number
|
|
||||||
mode: OpsRetryMode
|
|
||||||
status: 'running' | 'succeeded' | 'failed' | string
|
|
||||||
|
|
||||||
pinned_account_id?: number | null
|
|
||||||
used_account_id?: number | null
|
|
||||||
|
|
||||||
http_status_code: number
|
|
||||||
upstream_request_id: string
|
|
||||||
|
|
||||||
response_preview: string
|
|
||||||
response_truncated: boolean
|
|
||||||
|
|
||||||
error_message: string
|
|
||||||
|
|
||||||
started_at: string
|
|
||||||
finished_at: string
|
|
||||||
duration_ms: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OpsDashboardOverview {
|
export interface OpsDashboardOverview {
|
||||||
start_time: string
|
start_time: string
|
||||||
end_time: string
|
end_time: string
|
||||||
@ -946,13 +890,9 @@ export interface OpsErrorLog {
|
|||||||
platform: string
|
platform: string
|
||||||
model: string
|
model: string
|
||||||
|
|
||||||
is_retryable: boolean
|
|
||||||
retry_count: number
|
|
||||||
|
|
||||||
resolved: boolean
|
resolved: boolean
|
||||||
resolved_at?: string | null
|
resolved_at?: string | null
|
||||||
resolved_by_user_id?: number | null
|
resolved_by_user_id?: number | null
|
||||||
resolved_retry_id?: number | null
|
|
||||||
|
|
||||||
client_request_id: string
|
client_request_id: string
|
||||||
request_id: string
|
request_id: string
|
||||||
@ -994,10 +934,6 @@ export interface OpsErrorDetail extends OpsErrorLog {
|
|||||||
response_latency_ms?: number | null
|
response_latency_ms?: number | null
|
||||||
time_to_first_token_ms?: number | null
|
time_to_first_token_ms?: number | null
|
||||||
|
|
||||||
request_body: string
|
|
||||||
request_body_truncated: boolean
|
|
||||||
request_body_bytes?: number | null
|
|
||||||
|
|
||||||
is_business_limited: boolean
|
is_business_limited: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,16 +1092,6 @@ export async function getErrorLogDetail(id: number): Promise<OpsErrorDetail> {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function retryErrorRequest(id: number, req: OpsRetryRequest): Promise<OpsRetryResult> {
|
|
||||||
const { data } = await apiClient.post<OpsRetryResult>(`/admin/ops/errors/${id}/retry`, req)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function listRetryAttempts(errorId: number, limit = 50): Promise<OpsRetryAttempt[]> {
|
|
||||||
const { data } = await apiClient.get<OpsRetryAttempt[]>(`/admin/ops/errors/${errorId}/retries`, { params: { limit } })
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateErrorResolved(errorId: number, resolved: boolean): Promise<void> {
|
export async function updateErrorResolved(errorId: number, resolved: boolean): Promise<void> {
|
||||||
await apiClient.put(`/admin/ops/errors/${errorId}/resolve`, { resolved })
|
await apiClient.put(`/admin/ops/errors/${errorId}/resolve`, { resolved })
|
||||||
}
|
}
|
||||||
@ -1191,21 +1117,6 @@ export async function getUpstreamErrorDetail(id: number): Promise<OpsErrorDetail
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function retryRequestErrorClient(id: number): Promise<OpsRetryResult> {
|
|
||||||
const { data } = await apiClient.post<OpsRetryResult>(`/admin/ops/request-errors/${id}/retry-client`, {})
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function retryRequestErrorUpstreamEvent(id: number, idx: number): Promise<OpsRetryResult> {
|
|
||||||
const { data } = await apiClient.post<OpsRetryResult>(`/admin/ops/request-errors/${id}/upstream-errors/${idx}/retry`, {})
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function retryUpstreamError(id: number): Promise<OpsRetryResult> {
|
|
||||||
const { data } = await apiClient.post<OpsRetryResult>(`/admin/ops/upstream-errors/${id}/retry`, {})
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function updateRequestErrorResolved(errorId: number, resolved: boolean): Promise<void> {
|
export async function updateRequestErrorResolved(errorId: number, resolved: boolean): Promise<void> {
|
||||||
await apiClient.put(`/admin/ops/request-errors/${errorId}/resolve`, { resolved })
|
await apiClient.put(`/admin/ops/request-errors/${errorId}/resolve`, { resolved })
|
||||||
}
|
}
|
||||||
@ -1380,8 +1291,6 @@ export const opsAPI = {
|
|||||||
// Legacy unified endpoints
|
// Legacy unified endpoints
|
||||||
listErrorLogs,
|
listErrorLogs,
|
||||||
getErrorLogDetail,
|
getErrorLogDetail,
|
||||||
retryErrorRequest,
|
|
||||||
listRetryAttempts,
|
|
||||||
updateErrorResolved,
|
updateErrorResolved,
|
||||||
|
|
||||||
// New split endpoints
|
// New split endpoints
|
||||||
@ -1389,9 +1298,6 @@ export const opsAPI = {
|
|||||||
listUpstreamErrors,
|
listUpstreamErrors,
|
||||||
getRequestErrorDetail,
|
getRequestErrorDetail,
|
||||||
getUpstreamErrorDetail,
|
getUpstreamErrorDetail,
|
||||||
retryRequestErrorClient,
|
|
||||||
retryRequestErrorUpstreamEvent,
|
|
||||||
retryUpstreamError,
|
|
||||||
updateRequestErrorResolved,
|
updateRequestErrorResolved,
|
||||||
updateUpstreamErrorResolved,
|
updateUpstreamErrorResolved,
|
||||||
listRequestErrorUpstreamErrors,
|
listRequestErrorUpstreamErrors,
|
||||||
|
|||||||
@ -4636,20 +4636,13 @@ export default {
|
|||||||
titleWithId: 'Error #{id}',
|
titleWithId: 'Error #{id}',
|
||||||
noErrorSelected: 'No error selected.',
|
noErrorSelected: 'No error selected.',
|
||||||
resolution: 'Resolved:',
|
resolution: 'Resolved:',
|
||||||
pinnedToOriginalAccountId: 'Pinned to original account_id',
|
|
||||||
missingUpstreamRequestBody: 'Missing upstream request body',
|
|
||||||
failedToLoadRetryHistory: 'Failed to load retry history',
|
|
||||||
failedToUpdateResolvedStatus: 'Failed to update resolved status',
|
failedToUpdateResolvedStatus: 'Failed to update resolved status',
|
||||||
unsupportedRetryMode: 'Unsupported retry mode',
|
|
||||||
classificationKeys: {
|
classificationKeys: {
|
||||||
phase: 'Phase',
|
phase: 'Phase',
|
||||||
owner: 'Owner',
|
owner: 'Owner',
|
||||||
source: 'Source',
|
source: 'Source',
|
||||||
retryable: 'Retryable',
|
|
||||||
resolvedAt: 'Resolved At',
|
resolvedAt: 'Resolved At',
|
||||||
resolvedBy: 'Resolved By',
|
resolvedBy: 'Resolved By'
|
||||||
resolvedRetryId: 'Resolved Retry',
|
|
||||||
retryCount: 'Retry Count'
|
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
upstream_http: 'Upstream HTTP'
|
upstream_http: 'Upstream HTTP'
|
||||||
@ -4669,11 +4662,6 @@ export default {
|
|||||||
expand: 'Response (click to expand)',
|
expand: 'Response (click to expand)',
|
||||||
collapse: 'Response (click to collapse)'
|
collapse: 'Response (click to collapse)'
|
||||||
},
|
},
|
||||||
retryMeta: {
|
|
||||||
used: 'Used',
|
|
||||||
success: 'Success',
|
|
||||||
pinned: 'Pinned'
|
|
||||||
},
|
|
||||||
loading: 'Loading…',
|
loading: 'Loading…',
|
||||||
requestId: 'Request ID',
|
requestId: 'Request ID',
|
||||||
time: 'Time',
|
time: 'Time',
|
||||||
@ -4705,48 +4693,18 @@ export default {
|
|||||||
upstream: 'Upstream',
|
upstream: 'Upstream',
|
||||||
response: 'Response',
|
response: 'Response',
|
||||||
classification: 'Classification',
|
classification: 'Classification',
|
||||||
notRetryable: 'Not recommended to retry',
|
|
||||||
retry: 'Retry',
|
|
||||||
retryClient: 'Retry (Client)',
|
|
||||||
retryUpstream: 'Retry (Upstream pinned)',
|
|
||||||
pinnedAccountId: 'Pinned account_id',
|
|
||||||
retryNotes: 'Retry Notes',
|
|
||||||
requestBody: 'Request Body',
|
|
||||||
errorBody: 'Error Body',
|
errorBody: 'Error Body',
|
||||||
trimmed: 'trimmed',
|
trimmed: 'trimmed',
|
||||||
confirmRetry: 'Confirm Retry',
|
|
||||||
retrySuccess: 'Retry succeeded',
|
|
||||||
retryFailed: 'Retry failed',
|
|
||||||
retryHint: 'Retry will resend the request with the same parameters',
|
|
||||||
retryClientHint: 'Use client retry (no account pinning)',
|
|
||||||
retryUpstreamHint: 'Use upstream pinned retry (pin to the error account)',
|
|
||||||
pinnedAccountIdHint: '(auto from error log)',
|
|
||||||
retryNote1: 'Retry will use the same request body and parameters',
|
|
||||||
retryNote2: 'If the original request failed due to account issues, pinned retry may still fail',
|
|
||||||
retryNote3: 'Client retry will reselect an account',
|
|
||||||
retryNote4: 'You can force retry for non-retryable errors, but it is not recommended',
|
|
||||||
confirmRetryMessage: 'Confirm retry this request?',
|
|
||||||
confirmRetryHint: 'Will resend with the same request parameters',
|
|
||||||
forceRetry: 'I understand and want to force retry',
|
|
||||||
forceRetryHint: 'This error usually cannot be fixed by retry; check to proceed',
|
|
||||||
forceRetryNeedAck: 'Please check to force retry',
|
|
||||||
markResolved: 'Mark resolved',
|
markResolved: 'Mark resolved',
|
||||||
markUnresolved: 'Mark unresolved',
|
markUnresolved: 'Mark unresolved',
|
||||||
viewRetries: 'Retry history',
|
|
||||||
retryHistory: 'Retry History',
|
|
||||||
tabOverview: 'Overview',
|
tabOverview: 'Overview',
|
||||||
tabRetries: 'Retries',
|
|
||||||
tabRequest: 'Request',
|
tabRequest: 'Request',
|
||||||
tabResponse: 'Response',
|
tabResponse: 'Response',
|
||||||
responseBody: 'Response',
|
responseBody: 'Response',
|
||||||
compareA: 'Compare A',
|
compareA: 'Compare A',
|
||||||
compareB: 'Compare B',
|
compareB: 'Compare B',
|
||||||
retrySummary: 'Retry Summary',
|
|
||||||
responseHintSucceeded: 'Showing succeeded retry response_preview (#{id})',
|
|
||||||
responseHintFallback: 'No succeeded retry found; showing stored error_body',
|
|
||||||
suggestion: 'Suggestion',
|
suggestion: 'Suggestion',
|
||||||
suggestUpstreamResolved: '✓ Upstream error resolved by retry; no action needed',
|
suggestUpstream: 'Upstream instability: check account status or consider switching accounts',
|
||||||
suggestUpstream: 'Upstream instability: check account status, consider switching accounts, or retry',
|
|
||||||
suggestRequest: 'Client request error: ask customer to fix request parameters',
|
suggestRequest: 'Client request error: ask customer to fix request parameters',
|
||||||
suggestAuth: 'Auth failed: verify API key/credentials',
|
suggestAuth: 'Auth failed: verify API key/credentials',
|
||||||
suggestPlatform: 'Platform error: prioritize investigation and fix',
|
suggestPlatform: 'Platform error: prioritize investigation and fix',
|
||||||
|
|||||||
@ -4798,20 +4798,13 @@ export default {
|
|||||||
titleWithId: '错误 #{id}',
|
titleWithId: '错误 #{id}',
|
||||||
noErrorSelected: '未选择错误。',
|
noErrorSelected: '未选择错误。',
|
||||||
resolution: '已解决:',
|
resolution: '已解决:',
|
||||||
pinnedToOriginalAccountId: '固定到原 account_id',
|
|
||||||
missingUpstreamRequestBody: '缺少上游请求体',
|
|
||||||
failedToLoadRetryHistory: '加载重试历史失败',
|
|
||||||
failedToUpdateResolvedStatus: '更新解决状态失败',
|
failedToUpdateResolvedStatus: '更新解决状态失败',
|
||||||
unsupportedRetryMode: '不支持的重试模式',
|
|
||||||
classificationKeys: {
|
classificationKeys: {
|
||||||
phase: '阶段',
|
phase: '阶段',
|
||||||
owner: '归属方',
|
owner: '归属方',
|
||||||
source: '来源',
|
source: '来源',
|
||||||
retryable: '可重试',
|
|
||||||
resolvedAt: '解决时间',
|
resolvedAt: '解决时间',
|
||||||
resolvedBy: '解决人',
|
resolvedBy: '解决人'
|
||||||
resolvedRetryId: '解决重试ID',
|
|
||||||
retryCount: '重试次数'
|
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
upstream_http: '上游 HTTP'
|
upstream_http: '上游 HTTP'
|
||||||
@ -4831,11 +4824,6 @@ export default {
|
|||||||
expand: '响应内容(点击展开)',
|
expand: '响应内容(点击展开)',
|
||||||
collapse: '响应内容(点击收起)'
|
collapse: '响应内容(点击收起)'
|
||||||
},
|
},
|
||||||
retryMeta: {
|
|
||||||
used: '使用账号',
|
|
||||||
success: '成功',
|
|
||||||
pinned: '固定账号'
|
|
||||||
},
|
|
||||||
loading: '加载中…',
|
loading: '加载中…',
|
||||||
requestId: '请求 ID',
|
requestId: '请求 ID',
|
||||||
time: '时间',
|
time: '时间',
|
||||||
@ -4867,48 +4855,18 @@ export default {
|
|||||||
upstream: '上游',
|
upstream: '上游',
|
||||||
response: '响应',
|
response: '响应',
|
||||||
classification: '错误分类',
|
classification: '错误分类',
|
||||||
notRetryable: '此错误不建议重试',
|
|
||||||
retry: '重试',
|
|
||||||
retryClient: '重试(客户端)',
|
|
||||||
retryUpstream: '重试(上游固定)',
|
|
||||||
pinnedAccountId: '固定 account_id',
|
|
||||||
retryNotes: '重试说明',
|
|
||||||
requestBody: '请求体',
|
|
||||||
errorBody: '错误体',
|
errorBody: '错误体',
|
||||||
trimmed: '已截断',
|
trimmed: '已截断',
|
||||||
confirmRetry: '确认重试',
|
|
||||||
retrySuccess: '重试成功',
|
|
||||||
retryFailed: '重试失败',
|
|
||||||
retryHint: '重试将使用相同的请求参数重新发送请求',
|
|
||||||
retryClientHint: '使用客户端重试(不固定账号)',
|
|
||||||
retryUpstreamHint: '使用上游固定重试(固定到错误的账号)',
|
|
||||||
pinnedAccountIdHint: '(自动从错误日志获取)',
|
|
||||||
retryNote1: '重试会使用相同的请求体和参数',
|
|
||||||
retryNote2: '如果原请求失败是因为账号问题,固定重试可能仍会失败',
|
|
||||||
retryNote3: '客户端重试会重新选择账号',
|
|
||||||
retryNote4: '对不可重试的错误可以强制重试,但不推荐',
|
|
||||||
confirmRetryMessage: '确认要重试该请求吗?',
|
|
||||||
confirmRetryHint: '将使用相同的请求参数重新发送',
|
|
||||||
forceRetry: '我已确认并理解强制重试风险',
|
|
||||||
forceRetryHint: '此错误类型通常不可通过重试解决;如仍需重试请勾选确认',
|
|
||||||
forceRetryNeedAck: '请先勾选确认再强制重试',
|
|
||||||
markResolved: '标记已解决',
|
markResolved: '标记已解决',
|
||||||
markUnresolved: '标记未解决',
|
markUnresolved: '标记未解决',
|
||||||
viewRetries: '重试历史',
|
|
||||||
retryHistory: '重试历史',
|
|
||||||
tabOverview: '概览',
|
tabOverview: '概览',
|
||||||
tabRetries: '重试历史',
|
|
||||||
tabRequest: '请求详情',
|
tabRequest: '请求详情',
|
||||||
tabResponse: '响应详情',
|
tabResponse: '响应详情',
|
||||||
responseBody: '响应详情',
|
responseBody: '响应详情',
|
||||||
compareA: '对比 A',
|
compareA: '对比 A',
|
||||||
compareB: '对比 B',
|
compareB: '对比 B',
|
||||||
retrySummary: '重试摘要',
|
|
||||||
responseHintSucceeded: '展示重试成功的 response_preview(#{id})',
|
|
||||||
responseHintFallback: '没有成功的重试结果,展示存储的 error_body',
|
|
||||||
suggestion: '处理建议',
|
suggestion: '处理建议',
|
||||||
suggestUpstreamResolved: '✓ 上游错误已通过重试解决,无需人工介入',
|
suggestUpstream: '⚠️ 上游服务不稳定,建议:检查上游账号状态 / 考虑切换账号',
|
||||||
suggestUpstream: '⚠️ 上游服务不稳定,建议:检查上游账号状态 / 考虑切换账号 / 再次重试',
|
|
||||||
suggestRequest: '⚠️ 客户端请求错误,建议:联系客户修正请求参数 / 手动标记已解决',
|
suggestRequest: '⚠️ 客户端请求错误,建议:联系客户修正请求参数 / 手动标记已解决',
|
||||||
suggestAuth: '⚠️ 认证失败,建议:检查 API Key 是否有效 / 联系客户更新凭证',
|
suggestAuth: '⚠️ 认证失败,建议:检查 API Key 是否有效 / 联系客户更新凭证',
|
||||||
suggestPlatform: '🚨 平台错误,建议立即排查修复',
|
suggestPlatform: '🚨 平台错误,建议立即排查修复',
|
||||||
|
|||||||
@ -14,8 +14,6 @@ function makeDetail(overrides: Partial<OpsErrorDetail>): OpsErrorDetail {
|
|||||||
status_code: 502,
|
status_code: 502,
|
||||||
platform: 'openai',
|
platform: 'openai',
|
||||||
model: 'gpt-4o-mini',
|
model: 'gpt-4o-mini',
|
||||||
is_retryable: true,
|
|
||||||
retry_count: 0,
|
|
||||||
resolved: false,
|
resolved: false,
|
||||||
client_request_id: 'crid-1',
|
client_request_id: 'crid-1',
|
||||||
request_id: 'rid-1',
|
request_id: 'rid-1',
|
||||||
@ -25,8 +23,6 @@ function makeDetail(overrides: Partial<OpsErrorDetail>): OpsErrorDetail {
|
|||||||
group_name: 'group',
|
group_name: 'group',
|
||||||
error_body: '',
|
error_body: '',
|
||||||
user_agent: '',
|
user_agent: '',
|
||||||
request_body: '',
|
|
||||||
request_body_truncated: false,
|
|
||||||
is_business_limited: false,
|
is_business_limited: false,
|
||||||
...overrides
|
...overrides
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user