mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
Fix usage provider stats and performance analysis UI
This commit is contained in:
@@ -589,15 +589,20 @@ fn usage_matches_performance_percentiles_query(
|
||||
&& item.status == "completed"
|
||||
}
|
||||
|
||||
fn usage_reserved_provider_label(value: &str) -> bool {
|
||||
matches!(
|
||||
value.trim().to_ascii_lowercase().as_str(),
|
||||
"unknown" | "unknow" | "pending"
|
||||
)
|
||||
}
|
||||
|
||||
fn usage_provider_performance_identity(item: &StoredRequestUsageAudit) -> Option<(String, String)> {
|
||||
let provider_id = item.provider_id.as_deref()?.trim();
|
||||
let provider_id_status = provider_id.to_ascii_lowercase();
|
||||
if provider_id.is_empty() || matches!(provider_id_status.as_str(), "unknown" | "pending") {
|
||||
if provider_id.is_empty() || usage_reserved_provider_label(provider_id) {
|
||||
return None;
|
||||
}
|
||||
let provider_name = item.provider_name.trim();
|
||||
let provider_name_status = provider_name.to_ascii_lowercase();
|
||||
if matches!(provider_name_status.as_str(), "unknown" | "pending") {
|
||||
if usage_reserved_provider_label(provider_name) {
|
||||
return None;
|
||||
}
|
||||
let display_name = if provider_name.is_empty() {
|
||||
@@ -960,10 +965,10 @@ fn usage_output_tps_duration_ms(item: &StoredRequestUsageAudit) -> Option<u64> {
|
||||
|
||||
fn usage_provider_display_name(item: &StoredRequestUsageAudit) -> Option<String> {
|
||||
let provider_name = item.provider_name.trim();
|
||||
if provider_name.is_empty() || matches!(provider_name, "unknown" | "pending") {
|
||||
if provider_name.is_empty() || usage_reserved_provider_label(provider_name) {
|
||||
None
|
||||
} else {
|
||||
Some(item.provider_name.clone())
|
||||
Some(provider_name.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,12 +1159,31 @@ impl UsageReadRepository for InMemoryUsageReadRepository {
|
||||
continue;
|
||||
}
|
||||
|
||||
let provider_display_name =
|
||||
if matches!(query.group_by, UsageAuditAggregationGroupBy::Provider) {
|
||||
match usage_provider_display_name(item) {
|
||||
Some(value) => Some(value),
|
||||
None => continue,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let group_key = match query.group_by {
|
||||
UsageAuditAggregationGroupBy::Model => item.model.clone(),
|
||||
UsageAuditAggregationGroupBy::Provider => item
|
||||
.provider_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| "unknown".to_string()),
|
||||
UsageAuditAggregationGroupBy::Provider => {
|
||||
let display_name = provider_display_name
|
||||
.as_deref()
|
||||
.expect("provider display name is set for provider aggregation");
|
||||
item.provider_id
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|provider_id| {
|
||||
!provider_id.is_empty() && !usage_reserved_provider_label(provider_id)
|
||||
})
|
||||
.unwrap_or(display_name)
|
||||
.to_string()
|
||||
}
|
||||
UsageAuditAggregationGroupBy::ApiFormat => item
|
||||
.api_format
|
||||
.clone()
|
||||
@@ -1174,8 +1198,7 @@ impl UsageReadRepository for InMemoryUsageReadRepository {
|
||||
&& (bucket.display_name.is_none()
|
||||
|| bucket.display_name.as_deref() == Some("Unknown"))
|
||||
{
|
||||
bucket.display_name =
|
||||
usage_provider_display_name(item).or(Some("Unknown".to_string()));
|
||||
bucket.display_name = provider_display_name;
|
||||
}
|
||||
bucket.request_count = bucket.request_count.saturating_add(1);
|
||||
bucket.total_tokens = bucket.total_tokens.saturating_add(item.total_tokens);
|
||||
@@ -2909,7 +2932,8 @@ mod tests {
|
||||
UsageWriteRepository,
|
||||
};
|
||||
use aether_data_contracts::repository::usage::{
|
||||
usage_body_ref, UsageBodyField, UsageProviderPerformanceQuery, UsageTimeSeriesGranularity,
|
||||
usage_body_ref, UsageAuditAggregationGroupBy, UsageAuditAggregationQuery, UsageBodyField,
|
||||
UsageProviderPerformanceQuery, UsageTimeSeriesGranularity,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
@@ -3044,6 +3068,37 @@ mod tests {
|
||||
assert_eq!(usage.total_tokens, 150);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn provider_aggregation_skips_unknown_provider_labels() {
|
||||
let mut unknown = sample_usage("req-unknown-provider", 100);
|
||||
unknown.provider_id = None;
|
||||
unknown.provider_name = "unknown".to_string();
|
||||
|
||||
let mut typo_unknown = sample_usage("req-unknow-provider", 200);
|
||||
typo_unknown.provider_id = Some("unknow".to_string());
|
||||
typo_unknown.provider_name = "unknow".to_string();
|
||||
|
||||
let repository = InMemoryUsageReadRepository::seed(vec![
|
||||
sample_usage("req-valid-provider", 300),
|
||||
unknown,
|
||||
typo_unknown,
|
||||
]);
|
||||
|
||||
let rows = repository
|
||||
.aggregate_usage_audits(&UsageAuditAggregationQuery {
|
||||
created_from_unix_secs: 0,
|
||||
created_until_unix_secs: 1_000,
|
||||
group_by: UsageAuditAggregationGroupBy::Provider,
|
||||
limit: 10,
|
||||
})
|
||||
.await
|
||||
.expect("aggregation should succeed");
|
||||
|
||||
assert_eq!(rows.len(), 1);
|
||||
assert_eq!(rows[0].group_key, "provider-1");
|
||||
assert_eq!(rows[0].display_name.as_deref(), Some("OpenAI"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn stale_pending_update_does_not_regress_finalized_usage() {
|
||||
let repository = InMemoryUsageReadRepository::default();
|
||||
|
||||
@@ -1363,12 +1363,11 @@ fn usage_audit_aggregation_sql_fragments(
|
||||
success_count_expr: "NULL::BIGINT",
|
||||
},
|
||||
UsageAuditAggregationGroupBy::Provider => UsageAuditAggregationSqlFragments {
|
||||
filtered_extra_where: "",
|
||||
filtered_extra_where: " AND BTRIM(COALESCE(\"usage\".provider_name, '')) <> '' AND lower(BTRIM(COALESCE(\"usage\".provider_name, ''))) NOT IN ('unknown', 'unknow', 'pending')",
|
||||
group_key_expr: "provider_group_key",
|
||||
display_name_expr: "provider_display_name",
|
||||
secondary_name_expr: "NULL::varchar",
|
||||
aggregate_display_name_expr:
|
||||
"COALESCE(MAX(NULLIF(display_name, 'Unknown')), 'Unknown')",
|
||||
aggregate_display_name_expr: "MAX(display_name)",
|
||||
aggregate_secondary_name_expr: "NULL::varchar",
|
||||
avg_response_time_expr: "AVG(response_time_ms::DOUBLE PRECISION)",
|
||||
success_count_expr: "COALESCE(SUM(success_flag), 0)::BIGINT",
|
||||
@@ -6474,12 +6473,17 @@ WITH filtered_usage AS (
|
||||
SELECT
|
||||
"usage".model AS model,
|
||||
"usage".user_id AS user_id,
|
||||
COALESCE("usage".provider_id, 'unknown') AS provider_group_key,
|
||||
CASE
|
||||
WHEN BTRIM(COALESCE("usage".provider_id, '')) = ''
|
||||
OR lower(BTRIM(COALESCE("usage".provider_id, ''))) IN ('unknown', 'unknow', 'pending')
|
||||
THEN BTRIM("usage".provider_name)
|
||||
ELSE BTRIM("usage".provider_id)
|
||||
END AS provider_group_key,
|
||||
CASE
|
||||
WHEN BTRIM(COALESCE("usage".provider_name, '')) = ''
|
||||
OR "usage".provider_name IN ('unknown', 'pending')
|
||||
THEN 'Unknown'
|
||||
ELSE "usage".provider_name
|
||||
OR lower(BTRIM(COALESCE("usage".provider_name, ''))) IN ('unknown', 'unknow', 'pending')
|
||||
THEN NULL
|
||||
ELSE BTRIM("usage".provider_name)
|
||||
END AS provider_display_name,
|
||||
COALESCE("usage".api_format, 'unknown') AS api_format_group_key,
|
||||
GREATEST(COALESCE("usage".input_tokens, 0), 0) AS input_tokens,
|
||||
|
||||
@@ -414,6 +414,16 @@ fn usage_sql_aggregate_usage_audits_supports_daily_model_and_provider_aggregates
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_sql_provider_aggregation_excludes_unknown_provider_labels() {
|
||||
let source = include_str!("mod.rs");
|
||||
assert!(source.contains(
|
||||
r#"lower(BTRIM(COALESCE(\"usage\".provider_name, ''))) NOT IN ('unknown', 'unknow', 'pending')"#
|
||||
));
|
||||
assert!(source.contains("MAX(display_name)"));
|
||||
assert!(!source.contains("COALESCE(MAX(NULLIF(display_name, 'Unknown')), 'Unknown')"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_sql_summarize_total_tokens_by_api_key_ids_supports_daily_aggregates() {
|
||||
let source = include_str!("mod.rs");
|
||||
|
||||
Reference in New Issue
Block a user