mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
Use literal contains filters for usage names and models, align Key Usage filtering, and remove unused usage query parameters. Optimize summary aggregation, record counting, quota reads, and credential cooldown lookups without adding indexes. Co-authored-by: Codex <noreply@openai.com>
449 lines
12 KiB
TypeScript
449 lines
12 KiB
TypeScript
import type { RequestOptions } from '../request'
|
|
import type { AnalyticsMetadata } from './analytics'
|
|
import { API_BASE_URL } from '../constants'
|
|
import request from '../request'
|
|
|
|
export interface UsageTokenDetails {
|
|
inputTokens: number | null
|
|
outputTokens: number | null
|
|
cachedInputTokens: number | null
|
|
cacheWriteInputTokens: number | null
|
|
reasoningOutputTokens: number | null
|
|
imageInputTokens: number | null
|
|
imageOutputTokens: number | null
|
|
totalTokens: number | null
|
|
inputTokensDisplay: string
|
|
outputTokensDisplay: string
|
|
cachedInputTokensDisplay: string
|
|
cacheWriteInputTokensDisplay: string
|
|
reasoningOutputTokensDisplay: string
|
|
imageInputTokensDisplay: string
|
|
imageOutputTokensDisplay: string
|
|
totalTokensDisplay: string
|
|
}
|
|
|
|
export interface UsageCost {
|
|
currency: string
|
|
estimatedAmount: string
|
|
}
|
|
|
|
export interface UsageCostCoverage {
|
|
known: number
|
|
partial: number
|
|
unknown: number
|
|
notBillable: number
|
|
}
|
|
|
|
export interface UsageBilling {
|
|
longContextBillingApplied: boolean
|
|
image?: {
|
|
inputAmountDisplay: string
|
|
cacheReadAmountDisplay: string
|
|
inputPriceDisplay: string
|
|
cacheReadPriceDisplay: string
|
|
}
|
|
inputAmountDisplay: string
|
|
outputAmountDisplay: string
|
|
cacheReadAmountDisplay: string
|
|
cacheWriteAmountDisplay: string
|
|
standardAmountDisplay: string
|
|
totalAmountDisplay: string
|
|
inputPriceDisplay: string
|
|
outputPriceDisplay: string
|
|
cacheReadPriceDisplay: string
|
|
cacheWritePriceDisplay: string
|
|
serviceTierDisplay: string
|
|
multiplierDisplay: string
|
|
}
|
|
|
|
export interface UsageLatencyDetails {
|
|
upstreamResponseMs?: number
|
|
upstreamApiOverheadMs?: number
|
|
upstreamEngineMs?: number
|
|
admissionDecisionMs?: number
|
|
accountSelectionWaitMs?: number
|
|
capacityUsedSlots?: number
|
|
capacityTotalSlots?: number
|
|
transportDecisionWaitMs?: number
|
|
wsConnectMs?: number
|
|
upstreamHeadersMs?: number
|
|
firstEventMs?: number
|
|
firstReasoningMs?: number
|
|
firstTextMs?: number
|
|
openaiProcessingMs?: number
|
|
}
|
|
|
|
// Provider 私有观测字段;Core 字段由顶层 UsageRecord 提供,不再复制进 metadata。
|
|
export interface UsageRecordMetadata {
|
|
[key: string]: unknown
|
|
}
|
|
|
|
export type UsageRecordStatus = 'success' | 'error' | 'all'
|
|
|
|
export interface UsageListRecord {
|
|
logicalOutcome: string
|
|
errorCode: string | null
|
|
errorMessage: string | null
|
|
clientApiKeyName: string | null
|
|
id: string
|
|
provider: string | null
|
|
authenticationKind: string | null
|
|
accountId: string | null
|
|
accountEmail: string | null
|
|
accountName: string | null
|
|
accountNotes: string | null
|
|
accountPlanType: string | null
|
|
accountPlanTypeDisplay: string | null
|
|
route: string
|
|
model: string | null
|
|
requestedModel: string | null
|
|
upstreamModel: string | null
|
|
upstreamResponseModel: string | null
|
|
serviceTier: string | null
|
|
clientTransport: string
|
|
upstreamTransport: string | null
|
|
reasoningEffort: string | null
|
|
reasoningPreset: string | null
|
|
subagentKind: string | null
|
|
compact: boolean
|
|
tokenDetails: UsageTokenDetails
|
|
billing: UsageBilling | null
|
|
latencyDetails: UsageLatencyDetails
|
|
firstTokenLatencyMs: number | null
|
|
latencyMs: number | null
|
|
createdAt: string
|
|
createdAtDisplay: string
|
|
clientIp: string | null
|
|
userAgent: string | null
|
|
}
|
|
|
|
export interface UsageRecord {
|
|
id: string
|
|
requestId: string
|
|
clientApiKeyId: string | null
|
|
kind: string
|
|
provider: string | null
|
|
authenticationKind: string | null
|
|
accountId: string | null
|
|
accountEmail: string | null
|
|
accountName: string | null
|
|
route: string
|
|
model: string | null
|
|
requestedModel: string | null
|
|
upstreamModel: string | null
|
|
upstreamResponseModel: string | null
|
|
serviceTier: string | null
|
|
statusCode: number | null
|
|
clientTransport: string
|
|
upstreamTransport: string | null
|
|
protocol: string
|
|
httpVersion: string | null
|
|
clientStatusCode: number | null
|
|
upstreamStatusCode: number | null
|
|
websocketPool: { kind: string } | null
|
|
imageGenerationRequested: boolean
|
|
imageGenerationSucceeded: boolean | null
|
|
latencyDetails: UsageLatencyDetails | null
|
|
attemptIndex: number | null
|
|
attemptCount: number
|
|
responseId: string | null
|
|
upstreamRequestId: string | null
|
|
latencyMs: number | null
|
|
inputTokens: number | null
|
|
outputTokens: number | null
|
|
cachedInputTokens: number | null
|
|
cacheWriteInputTokens: number | null
|
|
reasoningOutputTokens: number | null
|
|
imageInputTokens: number | null
|
|
imageOutputTokens: number | null
|
|
message: string
|
|
metadata: UsageRecordMetadata
|
|
createdAt: string
|
|
createdAtDisplay: string
|
|
clientIp: string | null
|
|
userAgent: string | null
|
|
reasoningEffort: string | null
|
|
reasoningPreset: string | null
|
|
compact: boolean | null
|
|
requestKind: string | null
|
|
subagentKind: string | null
|
|
tokenDetails: UsageTokenDetails
|
|
billing: UsageBilling | null
|
|
costs: UsageCost[]
|
|
costCoverage: UsageCostCoverage
|
|
firstTokenLatencyMs: number | null
|
|
latencyMsDisplay: string
|
|
logicalOutcome: string
|
|
}
|
|
|
|
export interface UsageAttempt {
|
|
id: string
|
|
attemptIndex: number
|
|
trigger: string
|
|
provider: string
|
|
model: string | null
|
|
transport: string
|
|
sendState: string
|
|
outcome: string
|
|
downstreamCommitted: boolean
|
|
statusCode: number | null
|
|
providerErrorCode: string | null
|
|
failureClass: string | null
|
|
costEstimateStatus: string
|
|
estimatedCostAmount: string | null
|
|
estimatedCostCurrency: string | null
|
|
inputTokens: number | null
|
|
outputTokens: number | null
|
|
cachedInputTokens: number | null
|
|
totalTokens: number | null
|
|
firstTokenMs: number | null
|
|
latencyMs: number | null
|
|
credentialName: string | null
|
|
accountId: string | null
|
|
accountName: string | null
|
|
accountEmail: string | null
|
|
authenticationKind: string | null
|
|
startedAt: string
|
|
completedAt: string | null
|
|
}
|
|
|
|
export type UsageRecordDetail = UsageRecord & {
|
|
attempts: UsageAttempt[]
|
|
/** 尝试列表是否完整;best-effort 下恒为 false。 */
|
|
attemptsComplete: boolean
|
|
}
|
|
|
|
export interface UsageRecordsResponse {
|
|
items: UsageListRecord[]
|
|
currentPage: number
|
|
pageSize: number
|
|
total: number
|
|
}
|
|
|
|
export interface UsageSummaryResponse {
|
|
analytics: AnalyticsMetadata
|
|
totalRequests: string
|
|
inputTokens: string
|
|
outputTokens: string
|
|
cachedInputTokens: string
|
|
cacheWriteInputTokens: string
|
|
totalTokens: string
|
|
averageLatencyMs: string
|
|
}
|
|
|
|
export interface UsageOverviewHealthPoint {
|
|
bucket: string
|
|
label: string
|
|
totalRequests: number
|
|
successRequests: number
|
|
failedRequests: number
|
|
cancelledRequests: number
|
|
incompleteRequests: number
|
|
callerErrorRequests: number
|
|
errorRate: number
|
|
}
|
|
|
|
export interface UsageOverviewHealth {
|
|
totalRequests: number
|
|
successRequests: number
|
|
failedRequests: number
|
|
cancelledRequests: number
|
|
incompleteRequests: number
|
|
callerErrorRequests: number
|
|
successRate: number
|
|
completionRate: number
|
|
requestChangeRate: number | null
|
|
successRateChange: number | null
|
|
points: UsageOverviewHealthPoint[]
|
|
}
|
|
|
|
export interface UsageOverviewPerformancePoint {
|
|
bucket: string
|
|
label: string
|
|
latencyP50Ms: number | null
|
|
latencyP95Ms: number | null
|
|
latencyP99Ms: number | null
|
|
firstTokenP50Ms: number | null
|
|
firstTokenP95Ms: number | null
|
|
firstTokenP99Ms: number | null
|
|
admissionDecisionP50Ms: number | null
|
|
admissionDecisionP95Ms: number | null
|
|
accountSelectionWaitP50Ms: number | null
|
|
accountSelectionWaitP95Ms: number | null
|
|
outputThroughputP10: number | null
|
|
outputThroughputP50: number | null
|
|
outputThroughputP90: number | null
|
|
capacityUtilization: number | null
|
|
capacityUtilizationP95: number | null
|
|
}
|
|
|
|
export interface UsageOverviewPerformance {
|
|
latencyP50Ms: number | null
|
|
latencyP95Ms: number | null
|
|
latencyP99Ms: number | null
|
|
firstTokenP50Ms: number | null
|
|
firstTokenP95Ms: number | null
|
|
firstTokenP99Ms: number | null
|
|
admissionDecisionP50Ms: number | null
|
|
admissionDecisionP95Ms: number | null
|
|
accountSelectionWaitP50Ms: number | null
|
|
accountSelectionWaitP95Ms: number | null
|
|
outputThroughputP10: number | null
|
|
outputThroughputP50: number | null
|
|
outputThroughputP90: number | null
|
|
capacityUtilization: number | null
|
|
capacityUtilizationP95: number | null
|
|
latencyCoverage: number
|
|
firstTokenCoverage: number
|
|
admissionDecisionCoverage: number
|
|
accountSelectionWaitCoverage: number
|
|
capacityCoverage: number
|
|
points: UsageOverviewPerformancePoint[]
|
|
}
|
|
|
|
export interface UsageOverviewCostPoint {
|
|
bucket: string
|
|
label: string
|
|
inputTokens: number
|
|
outputTokens: number
|
|
cachedInputTokens: number
|
|
totalTokens: number
|
|
estimatedCost: string | null
|
|
standardCost: string | null
|
|
noCacheCost: string | null
|
|
cacheSavings: string | null
|
|
cachedTokenRate: number
|
|
cacheHitRequestRate: number | null
|
|
}
|
|
|
|
export interface UsageOverviewCost {
|
|
estimatedCost: string | null
|
|
standardCost: string | null
|
|
noCacheCost: string | null
|
|
cacheSavings: string | null
|
|
tierPremium: string | null
|
|
costPerRequest: string | null
|
|
costPerSuccessfulRequest: string | null
|
|
tokensPerRequest: number
|
|
cachedTokenRate: number
|
|
cacheHitRequestRate: number | null
|
|
inputTokens: number
|
|
outputTokens: number
|
|
cachedInputTokens: number
|
|
totalTokens: number
|
|
points: UsageOverviewCostPoint[]
|
|
coverage: UsageCostCoverage
|
|
}
|
|
|
|
export interface UsageInsightsOverviewResponse {
|
|
analytics: AnalyticsMetadata
|
|
granularity: string
|
|
health: UsageOverviewHealth
|
|
performance: UsageOverviewPerformance
|
|
cost: UsageOverviewCost
|
|
}
|
|
|
|
export interface UsageDiagnosticItem {
|
|
key: string
|
|
name: string
|
|
accountPlanType: string | null
|
|
accountPlanTypeDisplay: string | null
|
|
requestCount: number
|
|
successCount: number
|
|
errorCount: number
|
|
errorRate: number
|
|
requestShare: number
|
|
averageLatencyMs: number | null
|
|
latencyP95Ms: number | null
|
|
firstTokenP95Ms: number | null
|
|
nonCompletionCount: number
|
|
nonCompletionRate: number
|
|
retryCount: number
|
|
retryRate: number
|
|
estimatedCost: string | null
|
|
attemptCount: number
|
|
totalTokens: number
|
|
}
|
|
|
|
export interface UsageDiagnosticsResponse {
|
|
analytics: AnalyticsMetadata
|
|
dimension: string
|
|
items: UsageDiagnosticItem[]
|
|
}
|
|
|
|
// 请求参数类型:仅定义 API 边界的形状,调用方不依赖显式声明。
|
|
interface UsageRangeQuery {
|
|
startTime: string
|
|
endTime: string
|
|
provider?: string
|
|
}
|
|
|
|
interface PageQuery {
|
|
currentPage: number
|
|
pageSize: number
|
|
}
|
|
|
|
type UsagePageQuery = UsageRangeQuery & PageQuery & {
|
|
clientApiKeyName?: string
|
|
accountName?: string
|
|
model?: string
|
|
status?: UsageRecordStatus
|
|
}
|
|
|
|
interface UsageDetailQuery {
|
|
id: string
|
|
}
|
|
|
|
type UsageDiagnosticsQuery = UsageRangeQuery & { dimension: string, model?: string, statusCode?: number }
|
|
|
|
type DiagnosticsDownloadParams = { requestId: string } | { errorId: string }
|
|
|
|
export function getUsageRecords(data: UsagePageQuery, options: RequestOptions = {}) {
|
|
return request<UsageRecordsResponse>({
|
|
url: '/api/admin/usage/records',
|
|
method: 'GET',
|
|
params: data,
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function getUsageRecordDetail(data: UsageDetailQuery, options: RequestOptions = {}) {
|
|
return request<UsageRecordDetail>({
|
|
url: '/api/admin/usage/records/detail',
|
|
method: 'GET',
|
|
params: data,
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function getUsageRecordSummary(data: UsageRangeQuery, options: RequestOptions = {}) {
|
|
return request<UsageSummaryResponse>({
|
|
url: '/api/admin/usage/records/summary',
|
|
method: 'GET',
|
|
params: data,
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function getUsageRecordInsightsOverview(data: UsageRangeQuery, options: RequestOptions = {}) {
|
|
return request<UsageInsightsOverviewResponse>({
|
|
url: '/api/admin/usage/insights/overview',
|
|
method: 'GET',
|
|
params: data,
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function getUsageRecordInsightsDiagnostics(data: UsageDiagnosticsQuery, options: RequestOptions = {}) {
|
|
return request<UsageDiagnosticsResponse>({
|
|
url: '/api/admin/usage/insights/diagnostics',
|
|
method: 'GET',
|
|
params: data,
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function getDiagnosticsDownloadUrl(data: DiagnosticsDownloadParams) {
|
|
return `${API_BASE_URL}/api/admin/diagnostics/export?${new URLSearchParams(data)}`
|
|
}
|