feat(health): add model and provider health monitoring

- Rename the original health monitor to endpoint health monitor
- Add tab navigation for endpoint, model, and provider health views
- Add model health monitor cards with availability, latency, first-byte latency, and 60-point history
- Add admin-only provider health monitor with collapsible active-provider sections
- Show per-provider model health cards after expanding a provider
- Add backend model health and provider health monitor payload builders
- Add admin endpoint for provider health monitoring
- Add provider-scoped usage breakdown filtering for per-provider model statistics
- Add frontend API types and request helpers for model/provider health data
- Add demo mock data for model and provider health monitoring
- Fix model health timeline time-unit handling so request history segments render correctly

Verification:
- cargo fmt
- npm run type-check
- npm run build
- cargo test -p aether-gateway health_models
- cargo test -p aether-gateway health_providers
- cargo test -p aether-gateway gateway_exposes_frontdoor_manifest_without_proxying_upstream
This commit is contained in:
AAEE86
2026-05-28 12:00:20 +08:00
parent 14ad6e9b75
commit 4ce056fe45
24 changed files with 1914 additions and 17 deletions
@@ -4822,6 +4822,12 @@ WITH filtered_usage AS (
.push("\"usage\".user_id = ")
.push_bind(user_id.to_string());
}
if let Some(provider_name) = query.provider_name.as_deref() {
builder.push(if has_where { " AND " } else { " WHERE " });
builder
.push("\"usage\".provider_name = ")
.push_bind(provider_name.to_string());
}
builder.push(filtered_extra_where);
builder.push(
r#"
@@ -4914,6 +4920,9 @@ ORDER BY request_count DESC, group_key ASC
&self,
query: &UsageBreakdownSummaryQuery,
) -> Result<Vec<StoredUsageBreakdownSummaryRow>, DataLayerError> {
if query.provider_name.is_some() {
return self.summarize_usage_breakdown_raw(query).await;
}
let Some(user_id) = query.user_id.as_deref() else {
return self.summarize_usage_breakdown_raw(query).await;
};
@@ -4935,6 +4944,7 @@ ORDER BY request_count DESC, group_key ASC
created_from_unix_secs: dashboard_utc_to_unix_secs(raw_start),
created_until_unix_secs: dashboard_utc_to_unix_secs(raw_end),
user_id: Some(user_id.to_string()),
provider_name: None,
group_by: query.group_by,
})
.await?;
@@ -4957,6 +4967,7 @@ ORDER BY request_count DESC, group_key ASC
created_from_unix_secs: dashboard_utc_to_unix_secs(raw_start),
created_until_unix_secs: dashboard_utc_to_unix_secs(raw_end),
user_id: Some(user_id.to_string()),
provider_name: None,
group_by: query.group_by,
})
.await?;