Align admin user usage timing samples

This commit is contained in:
Novick Yuan
2026-05-28 14:30:15 +08:00
parent 9b5c3ecd23
commit 01c8592ca6
2 changed files with 62 additions and 7 deletions
@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const { getMock, cachedRequestMock, dedupedRequestMock, buildCacheKeyMock } = vi.hoisted(() => ({
getMock: vi.fn(),
@@ -29,6 +29,10 @@ describe('usageApi contract alignment', () => {
buildCacheKeyMock.mockClear()
})
afterEach(() => {
vi.restoreAllMocks()
})
it('loads current-user usage records from the Rust usage endpoint and normalizes pagination', async () => {
getMock.mockResolvedValueOnce({
data: {
@@ -115,6 +119,53 @@ describe('usageApi contract alignment', () => {
})
})
it('captures admin user usage server timing when the records request resolves', async () => {
let now = 1_000
vi.spyOn(Date, 'now').mockImplementation(() => now)
let resolveStats: ((value: unknown) => void) | null = null
getMock.mockImplementation((url: string) => {
if (url === '/api/admin/usage/stats') {
return new Promise(resolve => {
resolveStats = resolve
})
}
if (url === '/api/admin/usage/records') {
return Promise.resolve({
data: {
server_now_unix_ms: 10_050,
records: [{ id: 'record-3' }],
total: 1,
limit: 25,
offset: 0,
},
})
}
return Promise.reject(new Error(`unexpected url: ${url}`))
})
const resultPromise = usageApi.getUserUsage('user-123', { page: 1, page_size: 25 })
now = 1_100
await Promise.resolve()
now = 20_000
resolveStats?.({
data: {
total_requests: 1,
total_tokens: 10,
total_cost: 0.1,
avg_response_time: 500,
},
})
const result = await resultPromise
expect(result.server_timing).toEqual({
server_now_unix_ms: 10_050,
client_send_unix_ms: 1_000,
client_receive_unix_ms: 1_100,
})
})
it('uses an extended timeout and cache bypass option for admin analytics', async () => {
getMock
.mockResolvedValueOnce({
+10 -6
View File
@@ -458,17 +458,21 @@ export const usageApi = {
}> {
const statsParams = buildAdminUsageStatsParams(userId, filters)
const { params: recordParams } = buildAdminUsageRecordParams(userId, filters)
const clientSendUnixMs = beginServerTimingSample()
const statsRequest = apiClient.get<UsageStats>('/api/admin/usage/stats', { params: statsParams })
const recordsClientSendUnixMs = beginServerTimingSample()
const recordsRequest = apiClient
.get<UsageListResponse>('/api/admin/usage/records', { params: recordParams })
.then(response => withServerTiming(response.data, recordsClientSendUnixMs))
const [statsResponse, recordsResponse] = await Promise.all([
apiClient.get<UsageStats>('/api/admin/usage/stats', { params: statsParams }),
apiClient.get<UsageListResponse>('/api/admin/usage/records', { params: recordParams }),
statsRequest,
recordsRequest,
])
const recordsPayload = withServerTiming(recordsResponse.data, clientSendUnixMs)
return {
records: assertUsageRecords(recordsPayload.records),
records: assertUsageRecords(recordsResponse.records),
stats: statsResponse.data,
...(recordsPayload.server_timing ? { server_timing: recordsPayload.server_timing } : {}),
...(recordsResponse.server_timing ? { server_timing: recordsResponse.server_timing } : {}),
}
},