Show upstream model mapping (requested -> upstream) in UsageTable with arrow notation. Add requested/upstream/mapping source toggle to ModelDistributionChart with lazy loading — only fetches data when user switches tab, with per-source cache invalidation on filter changes. Include upstream_model column in Excel export and i18n for en/zh.
326 lines
7.7 KiB
TypeScript
326 lines
7.7 KiB
TypeScript
/**
|
|
* Admin Dashboard API endpoints
|
|
* Provides system-wide statistics and metrics
|
|
*/
|
|
|
|
import { apiClient } from '../client'
|
|
import type {
|
|
DashboardStats,
|
|
TrendDataPoint,
|
|
ModelStat,
|
|
GroupStat,
|
|
ApiKeyUsageTrendPoint,
|
|
UserUsageTrendPoint,
|
|
UserSpendingRankingResponse,
|
|
UserBreakdownItem,
|
|
UsageRequestType
|
|
} from '@/types'
|
|
|
|
/**
|
|
* Get dashboard statistics
|
|
* @returns Dashboard statistics including users, keys, accounts, and token usage
|
|
*/
|
|
export async function getStats(): Promise<DashboardStats> {
|
|
const { data } = await apiClient.get<DashboardStats>('/admin/dashboard/stats')
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Get real-time metrics
|
|
* @returns Real-time system metrics
|
|
*/
|
|
export async function getRealtimeMetrics(): Promise<{
|
|
active_requests: number
|
|
requests_per_minute: number
|
|
average_response_time: number
|
|
error_rate: number
|
|
}> {
|
|
const { data } = await apiClient.get<{
|
|
active_requests: number
|
|
requests_per_minute: number
|
|
average_response_time: number
|
|
error_rate: number
|
|
}>('/admin/dashboard/realtime')
|
|
return data
|
|
}
|
|
|
|
export interface TrendParams {
|
|
start_date?: string
|
|
end_date?: string
|
|
granularity?: 'day' | 'hour'
|
|
user_id?: number
|
|
api_key_id?: number
|
|
model?: string
|
|
account_id?: number
|
|
group_id?: number
|
|
request_type?: UsageRequestType
|
|
stream?: boolean
|
|
billing_type?: number | null
|
|
}
|
|
|
|
export interface TrendResponse {
|
|
trend: TrendDataPoint[]
|
|
start_date: string
|
|
end_date: string
|
|
granularity: string
|
|
}
|
|
|
|
/**
|
|
* Get usage trend data
|
|
* @param params - Query parameters for filtering
|
|
* @returns Usage trend data
|
|
*/
|
|
export async function getUsageTrend(params?: TrendParams): Promise<TrendResponse> {
|
|
const { data } = await apiClient.get<TrendResponse>('/admin/dashboard/trend', { params })
|
|
return data
|
|
}
|
|
|
|
export interface ModelStatsParams {
|
|
start_date?: string
|
|
end_date?: string
|
|
user_id?: number
|
|
api_key_id?: number
|
|
model?: string
|
|
model_source?: 'requested' | 'upstream' | 'mapping'
|
|
account_id?: number
|
|
group_id?: number
|
|
request_type?: UsageRequestType
|
|
stream?: boolean
|
|
billing_type?: number | null
|
|
}
|
|
|
|
export interface ModelStatsResponse {
|
|
models: ModelStat[]
|
|
start_date: string
|
|
end_date: string
|
|
}
|
|
|
|
/**
|
|
* Get model usage statistics
|
|
* @param params - Query parameters for filtering
|
|
* @returns Model usage statistics
|
|
*/
|
|
export async function getModelStats(params?: ModelStatsParams): Promise<ModelStatsResponse> {
|
|
const { data } = await apiClient.get<ModelStatsResponse>('/admin/dashboard/models', { params })
|
|
return data
|
|
}
|
|
|
|
export interface GroupStatsParams {
|
|
start_date?: string
|
|
end_date?: string
|
|
user_id?: number
|
|
api_key_id?: number
|
|
account_id?: number
|
|
group_id?: number
|
|
request_type?: UsageRequestType
|
|
stream?: boolean
|
|
billing_type?: number | null
|
|
}
|
|
|
|
export interface GroupStatsResponse {
|
|
groups: GroupStat[]
|
|
start_date: string
|
|
end_date: string
|
|
}
|
|
|
|
export interface DashboardSnapshotV2Params extends TrendParams {
|
|
include_stats?: boolean
|
|
include_trend?: boolean
|
|
include_model_stats?: boolean
|
|
include_group_stats?: boolean
|
|
include_users_trend?: boolean
|
|
users_trend_limit?: number
|
|
}
|
|
|
|
export interface DashboardSnapshotV2Stats extends DashboardStats {
|
|
uptime: number
|
|
}
|
|
|
|
export interface DashboardSnapshotV2Response {
|
|
generated_at: string
|
|
start_date: string
|
|
end_date: string
|
|
granularity: string
|
|
stats?: DashboardSnapshotV2Stats
|
|
trend?: TrendDataPoint[]
|
|
models?: ModelStat[]
|
|
groups?: GroupStat[]
|
|
users_trend?: UserUsageTrendPoint[]
|
|
}
|
|
|
|
/**
|
|
* Get group usage statistics
|
|
* @param params - Query parameters for filtering
|
|
* @returns Group usage statistics
|
|
*/
|
|
export async function getGroupStats(params?: GroupStatsParams): Promise<GroupStatsResponse> {
|
|
const { data } = await apiClient.get<GroupStatsResponse>('/admin/dashboard/groups', { params })
|
|
return data
|
|
}
|
|
|
|
export interface UserBreakdownParams {
|
|
start_date?: string
|
|
end_date?: string
|
|
group_id?: number
|
|
model?: string
|
|
model_source?: 'requested' | 'upstream' | 'mapping'
|
|
endpoint?: string
|
|
endpoint_type?: 'inbound' | 'upstream' | 'path'
|
|
limit?: number
|
|
}
|
|
|
|
export interface UserBreakdownResponse {
|
|
users: UserBreakdownItem[]
|
|
start_date: string
|
|
end_date: string
|
|
}
|
|
|
|
export async function getUserBreakdown(params: UserBreakdownParams): Promise<UserBreakdownResponse> {
|
|
const { data } = await apiClient.get<UserBreakdownResponse>('/admin/dashboard/user-breakdown', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Get dashboard snapshot v2 (aggregated response for heavy admin pages).
|
|
*/
|
|
export async function getSnapshotV2(params?: DashboardSnapshotV2Params): Promise<DashboardSnapshotV2Response> {
|
|
const { data } = await apiClient.get<DashboardSnapshotV2Response>('/admin/dashboard/snapshot-v2', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
export interface ApiKeyTrendParams extends TrendParams {
|
|
limit?: number
|
|
}
|
|
|
|
export interface ApiKeyTrendResponse {
|
|
trend: ApiKeyUsageTrendPoint[]
|
|
start_date: string
|
|
end_date: string
|
|
granularity: string
|
|
}
|
|
|
|
/**
|
|
* Get API key usage trend data
|
|
* @param params - Query parameters for filtering
|
|
* @returns API key usage trend data
|
|
*/
|
|
export async function getApiKeyUsageTrend(
|
|
params?: ApiKeyTrendParams
|
|
): Promise<ApiKeyTrendResponse> {
|
|
const { data } = await apiClient.get<ApiKeyTrendResponse>('/admin/dashboard/api-keys-trend', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
export interface UserTrendParams extends TrendParams {
|
|
limit?: number
|
|
}
|
|
|
|
export interface UserTrendResponse {
|
|
trend: UserUsageTrendPoint[]
|
|
start_date: string
|
|
end_date: string
|
|
granularity: string
|
|
}
|
|
|
|
export interface UserSpendingRankingParams
|
|
extends Pick<TrendParams, 'start_date' | 'end_date'> {
|
|
limit?: number
|
|
}
|
|
|
|
/**
|
|
* Get user usage trend data
|
|
* @param params - Query parameters for filtering
|
|
* @returns User usage trend data
|
|
*/
|
|
export async function getUserUsageTrend(params?: UserTrendParams): Promise<UserTrendResponse> {
|
|
const { data } = await apiClient.get<UserTrendResponse>('/admin/dashboard/users-trend', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Get user spending ranking data
|
|
* @param params - Query parameters for filtering
|
|
* @returns User spending ranking data
|
|
*/
|
|
export async function getUserSpendingRanking(
|
|
params?: UserSpendingRankingParams
|
|
): Promise<UserSpendingRankingResponse> {
|
|
const { data } = await apiClient.get<UserSpendingRankingResponse>('/admin/dashboard/users-ranking', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
export interface BatchUserUsageStats {
|
|
user_id: number
|
|
today_actual_cost: number
|
|
total_actual_cost: number
|
|
}
|
|
|
|
export interface BatchUsersUsageResponse {
|
|
stats: Record<string, BatchUserUsageStats>
|
|
}
|
|
|
|
/**
|
|
* Get batch usage stats for multiple users
|
|
* @param userIds - Array of user IDs
|
|
* @returns Usage stats map keyed by user ID
|
|
*/
|
|
export async function getBatchUsersUsage(userIds: number[]): Promise<BatchUsersUsageResponse> {
|
|
const { data } = await apiClient.post<BatchUsersUsageResponse>('/admin/dashboard/users-usage', {
|
|
user_ids: userIds
|
|
})
|
|
return data
|
|
}
|
|
|
|
export interface BatchApiKeyUsageStats {
|
|
api_key_id: number
|
|
today_actual_cost: number
|
|
total_actual_cost: number
|
|
}
|
|
|
|
export interface BatchApiKeysUsageResponse {
|
|
stats: Record<string, BatchApiKeyUsageStats>
|
|
}
|
|
|
|
/**
|
|
* Get batch usage stats for multiple API keys
|
|
* @param apiKeyIds - Array of API key IDs
|
|
* @returns Usage stats map keyed by API key ID
|
|
*/
|
|
export async function getBatchApiKeysUsage(
|
|
apiKeyIds: number[]
|
|
): Promise<BatchApiKeysUsageResponse> {
|
|
const { data } = await apiClient.post<BatchApiKeysUsageResponse>(
|
|
'/admin/dashboard/api-keys-usage',
|
|
{
|
|
api_key_ids: apiKeyIds
|
|
}
|
|
)
|
|
return data
|
|
}
|
|
|
|
export const dashboardAPI = {
|
|
getStats,
|
|
getRealtimeMetrics,
|
|
getUsageTrend,
|
|
getModelStats,
|
|
getGroupStats,
|
|
getSnapshotV2,
|
|
getApiKeyUsageTrend,
|
|
getUserUsageTrend,
|
|
getUserSpendingRanking,
|
|
getBatchUsersUsage,
|
|
getBatchApiKeysUsage
|
|
}
|
|
|
|
export default dashboardAPI
|