Files
Aether/frontend/src/api/requestTrace.ts
T
elky a90d564931 fix: restore security hardening compatibility and validation
Restore authorized rule reveal, explicit full HTTP capture and retention, video task business fields, and valid payment URLs. Add opt-in credential preservation for trusted recovery, fix frontend type contracts and async races, and eliminate PostgreSQL test fixture resource leaks. Document audit coverage and successful fmt and CI-scoped Clippy checks.
2026-09-07 21:14:27 +08:00

170 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import apiClient from './client'
export interface CandidateRankingMetadata {
mode?: string
priority_mode?: string
index?: number
priority_slot?: number
promoted_by?: string
demoted_by?: string
}
export interface ImageProgress {
phase?: 'upstream_connecting' | 'upstream_streaming' | 'upstream_completed' | 'failed' | string
upstream_ttfb_ms?: number | null
upstream_sse_frame_count?: number | null
last_upstream_event?: string | null
last_upstream_frame_at_unix_ms?: number | null
partial_image_count?: number | null
last_client_visible_event?: string | null
downstream_heartbeat_count?: number | null
last_downstream_heartbeat_at_unix_ms?: number | null
downstream_heartbeat_interval_ms?: number | null
}
export interface CandidateResponseBoundary {
source?: string
status_code?: number | null
headers?: Record<string, unknown> | null
body?: unknown
body_ref?: string | null
body_state?: string | null
}
export interface CandidateProxyTiming {
body_read_ms?: number | null
decompress_ms?: number | null
wire_size?: number | null
body_size?: number | null
ttfb_ms?: number | null
upstream_ms?: number | null
response_wait_ms?: number | null
connection_acquire_ms?: number | null
upstream_processing_ms?: number | null
connect_ms?: number | null
tls_ms?: number | null
dns_ms?: number | null
total_ms?: number | null
connection_reused?: boolean | null
}
export interface CandidateProxy {
node_name?: string | null
node_id?: string | null
url?: string | null
source?: string | null
ttfb_ms?: number | null
timing?: CandidateProxyTiming | null
}
export interface CandidateRecord {
id: string
request_id: string
candidate_index: number
retry_index: number
provider_id?: string
provider_name?: string
provider_website?: string // Provider 官网
provider_priority?: number
provider_keep_priority_on_conversion?: boolean
provider_enable_format_conversion?: boolean
endpoint_id?: string
endpoint_name?: string // 端点显示名称(api_format)
endpoint_api_family?: string
endpoint_kind?: string
endpoint_format_acceptance_config?: Record<string, unknown> | null
key_id?: string
key_name?: string // 密钥名称
key_account_label?: string // 更适合展示的测试账号标签(优先 OAuth 邮箱)
key_preview?: string // 密钥脱敏预览(如 sk-***abc),OAuth 类型不返回
key_auth_type?: string // 密钥认证类型(api_key, service_account, oauth 等)
key_api_formats?: unknown
key_internal_priority?: number
key_global_priority_by_format?: Record<string, number> | null
key_oauth_plan_type?: string // OAuth 账号套餐类型(free/plus/team/enterprise)
key_capabilities?: Record<string, boolean> | null // Key 支持的能力
required_capabilities?: Record<string, boolean> | null // 请求实际需要的能力标签
status: 'pending' | 'streaming' | 'success' | 'failed' | 'skipped' | 'cancelled' | 'available' | 'unused' | 'stream_interrupted'
skip_reason?: string
is_cached: boolean
// 执行结果字段
status_code?: number
error_type?: string
error_message?: string
latency_ms?: number
concurrent_requests?: number
ranking?: CandidateRankingMetadata | null
image_progress?: ImageProgress | null
extra_data?: Record<string, unknown> & {
first_byte_time_ms?: number | null
needs_conversion?: boolean
provider_api_format?: string | null
proxy?: CandidateProxy | null
pool_selection?: {
reason: string
cost_soft_threshold?: number | boolean | null
cost_window_usage?: number | null
cost_limit?: number | null
} | null
pool_skip?: {
type: string
cooldown_reason?: string | null
cooldown_ttl?: number | null
cost_window_usage?: number | null
} | null
upstream_response?: CandidateResponseBoundary
image_progress?: ImageProgress | null
}
created_at: string
started_at?: string
finished_at?: string
}
export interface RequestTrace {
request_id: string
request_path?: string
request_query_string?: string
request_path_and_query?: string
total_candidates: number
final_status: 'success' | 'failed' | 'streaming' | 'pending' | 'cancelled'
total_latency_ms: number
candidates: CandidateRecord[]
}
export interface ProviderStats {
total_attempts: number
success_count: number
failed_count: number
cancelled_count: number
skipped_count: number
pending_count: number
available_count: number
failure_rate: number
}
export const requestTraceApi = {
/**
* 获取特定请求的完整追踪信息
*/
async getRequestTrace(
requestId: string,
options: { attemptedOnly?: boolean } = {},
): Promise<RequestTrace> {
const attemptedOnly = options.attemptedOnly ?? false
const response = await apiClient.get<RequestTrace>(`/api/admin/monitoring/trace/${requestId}`, {
params: { attempted_only: attemptedOnly },
})
return response.data
},
/**
* 获取某个 Provider 的失败率统计
*/
async getProviderStats(providerId: string, limit: number = 100): Promise<ProviderStats> {
const response = await apiClient.get<ProviderStats>(`/api/admin/monitoring/trace/stats/provider/${providerId}`, {
params: { limit }
})
return response.data
}
}