feat: revamp analytics dashboards and harden database migrations

Add dashboard and overview analytics, health monitoring, provider expense tracking, and announcement updates across the gateway and frontend.

Keep schema migrations free of historical backfills while preserving automatic backfill execution. Bound migration deadlines, run schema preparation before Compose replacement, and anonymize deleted dashboard users.

Include the current documentation cleanup and regression coverage.
This commit is contained in:
elky
2026-10-01 11:48:17 +08:00
parent 60b89cc840
commit 066ea87d72
327 changed files with 31728 additions and 20645 deletions
+29 -1
View File
@@ -133,6 +133,8 @@ export interface UsageByApiFormat {
}
export interface UsageFilters {
from?: string
to?: string
user_id?: string // UUID
provider_id?: string // UUID
model?: string
@@ -499,6 +501,17 @@ export const usageApi = {
},
async getAllUsageRecords(params?: {
from?: string
to?: string
provider_id?: string
api_key_id?: string
request_id?: string
attribution_kind?: string
endpoint_kind?: string
request_type?: string
is_stream?: boolean
has_format_conversion?: boolean
slow_threshold_ms?: number
start_date?: string
end_date?: string
preset?: string
@@ -539,6 +552,17 @@ export const usageApi = {
},
async getAllUsageRecordTotal(params?: {
from?: string
to?: string
provider_id?: string
api_key_id?: string
request_id?: string
attribution_kind?: string
endpoint_kind?: string
request_type?: string
is_stream?: boolean
has_format_conversion?: boolean
slow_threshold_ms?: number
start_date?: string
end_date?: string
preset?: string
@@ -576,7 +600,7 @@ export const usageApi = {
*/
async getActiveRequests(
ids?: string[],
timeRange?: Pick<UsageFilters, 'start_date' | 'end_date' | 'preset' | 'timezone' | 'tz_offset_minutes'>
timeRange?: Pick<UsageFilters, 'from' | 'to' | 'start_date' | 'end_date' | 'preset' | 'timezone' | 'tz_offset_minutes'>
): Promise<{
requests: Array<{
id: string
@@ -629,6 +653,10 @@ export const usageApi = {
if (ids?.length) {
params.ids = ids.join(',')
}
if (timeRange?.from && timeRange.to) {
params.from = timeRange.from
params.to = timeRange.to
}
if (timeRange?.start_date) {
params.start_date = timeRange.start_date
}