refactor(rules): 规则引擎容错优化,无效规则条目跳过而非中止整个规则集

- header/body rules 的 _are_locally_supported 简化为仅检查是否为数组
- apply 逻辑中遇到格式错误/不支持的规则条目改为 continue 跳过,而非 return false
- 允许非字符串 header value,自动序列化为 JSON 字符串
- 宽松处理无效 regex flag,不再拒绝整条规则

fix(gateway): Claude CLI 路由仅检查 bearer 头,不排斥同时携带 x-api-key 的请求

feat(observability): 监控链路候选展示解密 auth_config 的账号标签和 OAuth 计划类型
This commit is contained in:
fawney19
2026-04-25 19:46:52 +08:00
parent 00744c0ce5
commit 912a92cd1a
7 changed files with 438 additions and 184 deletions

View File

@@ -12,6 +12,12 @@ use axum::{
use serde_json::{json, Value};
use std::collections::BTreeMap;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct AdminMonitoringKeyAccountDisplay {
pub label: Option<String>,
pub oauth_plan_type: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdminMonitoringRoute {
AuditLogs,
@@ -263,6 +269,18 @@ pub fn build_admin_monitoring_trace_provider_stats_payload_response(
pub fn build_admin_monitoring_trace_request_payload_response(
trace: &DecisionTrace,
usage: Option<&StoredRequestUsageAudit>,
) -> Response<Body> {
build_admin_monitoring_trace_request_payload_response_with_key_accounts(
trace,
usage,
&BTreeMap::new(),
)
}
pub fn build_admin_monitoring_trace_request_payload_response_with_key_accounts(
trace: &DecisionTrace,
usage: Option<&StoredRequestUsageAudit>,
key_accounts: &BTreeMap<String, AdminMonitoringKeyAccountDisplay>,
) -> Response<Body> {
let usage_candidate_id =
usage.and_then(|item| resolve_admin_monitoring_usage_candidate_id(trace, item));
@@ -274,7 +292,11 @@ pub fn build_admin_monitoring_trace_request_payload_response(
.as_deref()
.filter(|candidate_id| *candidate_id == item.candidate.id.as_str())
.and(usage);
build_admin_monitoring_trace_request_candidate_payload(item, matched_usage)
build_admin_monitoring_trace_request_candidate_payload_with_key_accounts(
item,
matched_usage,
key_accounts,
)
})
.collect::<Vec<_>>();
Json(json!({
@@ -290,8 +312,24 @@ pub fn build_admin_monitoring_trace_request_payload_response(
pub fn build_admin_monitoring_trace_request_candidate_payload(
item: &DecisionTraceCandidate,
usage: Option<&StoredRequestUsageAudit>,
) -> Value {
build_admin_monitoring_trace_request_candidate_payload_with_key_accounts(
item,
usage,
&BTreeMap::new(),
)
}
pub fn build_admin_monitoring_trace_request_candidate_payload_with_key_accounts(
item: &DecisionTraceCandidate,
usage: Option<&StoredRequestUsageAudit>,
key_accounts: &BTreeMap<String, AdminMonitoringKeyAccountDisplay>,
) -> Value {
let candidate = &item.candidate;
let key_account = candidate
.key_id
.as_deref()
.and_then(|key_id| key_accounts.get(key_id));
json!({
"id": candidate.id,
"request_id": candidate.request_id,
@@ -310,13 +348,13 @@ pub fn build_admin_monitoring_trace_request_candidate_payload(
"endpoint_format_acceptance_config": item.endpoint_format_acceptance_config,
"key_id": candidate.key_id,
"key_name": item.provider_key_name,
"key_account_label": serde_json::Value::Null,
"key_account_label": key_account.and_then(|item| item.label.clone()),
"key_preview": serde_json::Value::Null,
"key_auth_type": item.provider_key_auth_type,
"key_api_formats": item.provider_key_api_formats,
"key_internal_priority": item.provider_key_internal_priority,
"key_global_priority_by_format": item.provider_key_global_priority_by_format,
"key_oauth_plan_type": serde_json::Value::Null,
"key_oauth_plan_type": key_account.and_then(|item| item.oauth_plan_type.clone()),
"key_capabilities": item.provider_key_capabilities,
"required_capabilities": candidate.required_capabilities,
"status": candidate.status,