feat(stats): 新增聚合读路径与回填机制并重构 dashboard/usage 读取链路

- 新增 stats_user_summary 及 user_daily_provider/api_format/cost_savings 等聚合表
- 扩展 stats_daily/hourly 有效 token 与响应时间等字段,maintenance runtime 同步写入
- 新增 backfill 模块与 --apply-backfills 命令补齐历史聚合数据
- 重写 dashboard_filters、usage_heatmap、user_rollups 查询改走聚合表
- 同步更新 baseline_v2.sql 与 migration 集,README/dev.sh 补充回填用法
This commit is contained in:
fawney19
2026-04-22 17:29:39 +08:00
parent 063ef02306
commit a5e6bd3b62
45 changed files with 15323 additions and 1039 deletions

View File

@@ -104,6 +104,7 @@ fn sample_standalone_export_record(
Some(4_102_444_800),
false,
7,
0,
1.25,
true,
)

View File

@@ -414,6 +414,7 @@ fn sample_monitoring_export_api_key(
None,
false,
0,
0,
0.0,
false,
)

View File

@@ -635,6 +635,7 @@ async fn gateway_handles_admin_system_users_export_locally_with_trusted_admin_pr
Some(1_900_000_000),
false,
42,
420,
12.34,
false,
)
@@ -661,6 +662,7 @@ async fn gateway_handles_admin_system_users_export_locally_with_trusted_admin_pr
None,
false,
7,
84,
3.21,
true,
)
@@ -749,10 +751,15 @@ async fn gateway_handles_admin_system_users_export_locally_with_trusted_admin_pr
payload["users"][0]["api_keys"][0]["is_standalone"],
json!(false)
);
assert_eq!(
payload["users"][0]["api_keys"][0]["total_tokens"],
json!(420)
);
assert_eq!(
payload["standalone_keys"][0]["key"],
json!("ak-standalone-live-1")
);
assert_eq!(payload["standalone_keys"][0]["total_tokens"], json!(84));
assert_eq!(
payload["standalone_keys"][0]["wallet"]["unlimited"],
json!(true)

View File

@@ -607,6 +607,7 @@ async fn gateway_imports_admin_system_users_locally_and_persists_data() {
"expires_at": "2099-01-01T00:00:00Z",
"auto_delete_on_expiry": false,
"total_requests": 12,
"total_tokens": 3456,
"total_cost_usd": 1.25
}]
}],
@@ -622,6 +623,7 @@ async fn gateway_imports_admin_system_users_locally_and_persists_data() {
"expires_at": "2099-02-01T00:00:00Z",
"auto_delete_on_expiry": false,
"total_requests": 3,
"total_tokens": 789,
"total_cost_usd": 0.75,
"wallet": {
"balance": 30.0,
@@ -704,6 +706,7 @@ async fn gateway_imports_admin_system_users_locally_and_persists_data() {
.expect("user api keys should load");
assert_eq!(user_api_keys.len(), 1);
assert_eq!(user_api_keys[0].name.as_deref(), Some("Alice CLI"));
assert_eq!(user_api_keys[0].total_tokens, 3456);
assert_eq!(
user_api_keys[0].allowed_api_formats,
Some(vec!["openai:chat".to_string()])
@@ -729,6 +732,7 @@ async fn gateway_imports_admin_system_users_locally_and_persists_data() {
standalone_keys[0].name.as_deref(),
Some("Imported Standalone")
);
assert_eq!(standalone_keys[0].total_tokens, 789);
assert_eq!(
decrypt_python_fernet_ciphertext(
DEVELOPMENT_ENCRYPTION_KEY,

View File

@@ -674,6 +674,7 @@ async fn gateway_handles_admin_user_api_key_routes_locally_with_trusted_admin_pr
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -835,6 +836,7 @@ async fn gateway_returns_conflict_for_admin_create_user_api_key_when_writer_unav
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -963,6 +965,7 @@ async fn gateway_returns_conflict_for_admin_lock_user_api_key_when_writer_unavai
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -1088,6 +1091,7 @@ async fn gateway_returns_conflict_for_admin_update_user_api_key_when_writer_unav
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -1162,6 +1166,7 @@ async fn gateway_returns_conflict_for_admin_delete_user_api_key_when_writer_unav
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -1238,6 +1243,7 @@ async fn gateway_lists_admin_user_api_keys_locally_with_trusted_admin_principal(
Some(200),
false,
9,
0,
1.5,
false,
)
@@ -1428,6 +1434,7 @@ async fn gateway_reveals_admin_user_full_key_locally_with_trusted_admin_principa
Some(200),
false,
9,
0,
1.5,
false,
)