Feature/error request logging (#401)

* feat(proxy): add error mapper for HTTP status code mapping

- Add error_mapper.rs module to map ProxyError to HTTP status codes
- Implement map_proxy_error_to_status() for error classification
- Implement get_error_message() for user-friendly error messages
- Support all error types: upstream, timeout, connection, provider failures
- Include comprehensive unit tests for all mappings

* feat(proxy): enhance error logging with context support

- Add log_error_with_context() method for detailed error recording
- Support streaming flag, session_id, and provider_type fields
- Remove dead_code warning from log_error() method
- Enable comprehensive error request tracking in database

* feat(proxy): implement error capture and logging in all handlers

- Capture and log all failed requests in handle_messages (Claude)
- Capture and log all failed requests in handle_gemini (Gemini)
- Capture and log all failed requests in handle_responses (Codex)
- Capture and log all failed requests in handle_chat_completions (Codex)
- Record error status codes, messages, and latency for all failures
- Generate unique session_id for each request
- Support both streaming and non-streaming error scenarios

* style: fix clippy warnings and typescript errors

- Add allow(dead_code) for CircuitBreaker::get_state (reserved for future)
- Fix all uninlined format string warnings (27 instances)
- Use inline format syntax for better readability
- Fix unused import and parameter warnings in ProviderActions.tsx
- Achieve zero warnings in both Rust and TypeScript

* style: apply code formatting

- Remove trailing whitespace in misc.rs
- Add trailing comma in App.tsx
- Format multi-line className in ProviderCard.tsx

* feat(proxy): add settings button to proxy panel

Add configuration buttons in both running and stopped states to
provide easy access to proxy settings dialog.

* fix(speedtest): skip client build for invalid inputs

* chore(clippy): fix uninlined format args

* Merge branch 'main' into feature/error-request-logging
This commit is contained in:
YoVinchen
2025-12-16 21:02:08 +08:00
committed by GitHub
parent e6654bd7f9
commit ec20ff4d8c
13 changed files with 327 additions and 106 deletions
+5 -19
View File
@@ -48,17 +48,13 @@ impl FailoverSwitchManager {
provider_id: &str,
provider_name: &str,
) -> Result<bool, AppError> {
let switch_key = format!("{}:{}", app_type, provider_id);
let switch_key = format!("{app_type}:{provider_id}");
// 去重检查:如果相同切换已在进行中,跳过
{
let mut pending = self.pending_switches.write().await;
if pending.contains(&switch_key) {
log::debug!(
"[Failover] 切换已在进行中,跳过: {} -> {}",
app_type,
provider_id
);
log::debug!("[Failover] 切换已在进行中,跳过: {app_type} -> {provider_id}");
return Ok(false);
}
pending.insert(switch_key.clone());
@@ -85,19 +81,14 @@ impl FailoverSwitchManager {
provider_id: &str,
provider_name: &str,
) -> Result<bool, AppError> {
log::info!(
"[Failover] 开始切换供应商: {} -> {} ({})",
app_type,
provider_name,
provider_id
);
log::info!("[Failover] 开始切换供应商: {app_type} -> {provider_name} ({provider_id})");
// 1. 更新数据库 is_current
self.db.set_current_provider(app_type, provider_id)?;
// 2. 更新本地 settings(设备级)
let app_type_enum = crate::app_config::AppType::from_str(app_type)
.map_err(|_| AppError::Message(format!("无效的应用类型: {}", app_type)))?;
.map_err(|_| AppError::Message(format!("无效的应用类型: {app_type}")))?;
crate::settings::set_current_provider(&app_type_enum, Some(provider_id))?;
// 3. 更新托盘菜单和发射事件
@@ -136,12 +127,7 @@ impl FailoverSwitchManager {
}
}
log::info!(
"[Failover] 供应商切换完成: {} -> {} ({})",
app_type,
provider_name,
provider_id
);
log::info!("[Failover] 供应商切换完成: {app_type} -> {provider_name} ({provider_id})");
Ok(true)
}