feat: 添加超详细的HTTP请求日志系统

详细日志增强:
- HTTP请求URL和超时配置
- 完整的请求头信息 (Authorization脱敏显示)
- 请求体大小和内容预览
- HTTP响应状态码和原因短语
- 完整的响应头信息
- 响应体大小和内容预览

 重试机制日志:
- 每次尝试的详细时间统计
- 失败原因的具体记录
- 重试等待过程的状态显示
- 成功/失败的明确标识

 错误分析支持:
- JSON解析错误的详细信息
- 错误响应的完整内容
- 候选结果数量统计
- 内容预览和截断显示

 调试友好:
- 分步骤的详细日志
- 时间戳和耗时统计
- 敏感信息的安全处理
- 结构化的日志输出

现在可以完整分析API调用的每个环节!
This commit is contained in:
imeepos 2025-07-14 13:27:04 +08:00
parent ea2c72ea05
commit e626521ac2
1 changed files with 95 additions and 10 deletions

View File

@ -337,21 +337,31 @@ impl GeminiService {
// 重试机制 // 重试机制
let mut last_error = None; let mut last_error = None;
println!("🔄 开始重试机制,最大重试次数: {}", self.config.max_retries);
for attempt in 0..self.config.max_retries { for attempt in 0..self.config.max_retries {
println!("🔄 尝试 {}/{}", attempt + 1, self.config.max_retries); println!("🎯 === 第 {}/{} 次尝试 ===", attempt + 1, self.config.max_retries);
let attempt_start = std::time::Instant::now();
match self.send_generate_request(&generate_url, &client_config, &request_data).await { match self.send_generate_request(&generate_url, &client_config, &request_data).await {
Ok(result) => { Ok(result) => {
println!("✅ 成功获取Gemini分析结果"); let attempt_duration = attempt_start.elapsed();
println!("✅ 第 {} 次尝试成功!耗时: {:?}", attempt + 1, attempt_duration);
println!("🎉 成功获取Gemini分析结果");
return self.parse_gemini_response_content(&result); return self.parse_gemini_response_content(&result);
} }
Err(e) => { Err(e) => {
let attempt_duration = attempt_start.elapsed();
last_error = Some(e); last_error = Some(e);
println!("⚠️ 尝试 {}/{} 失败: {}", attempt + 1, self.config.max_retries, last_error.as_ref().unwrap()); println!("❌ 第 {} 次尝试失败,耗时: {:?}", attempt + 1, attempt_duration);
println!("📝 失败原因: {}", last_error.as_ref().unwrap());
if attempt < self.config.max_retries - 1 { if attempt < self.config.max_retries - 1 {
println!("⏳ 等待 {} 秒后重试...", self.config.retry_delay); println!("⏳ 等待 {} 秒后进行第 {}重试...", self.config.retry_delay, attempt + 2);
tokio::time::sleep(tokio::time::Duration::from_secs(self.config.retry_delay)).await; tokio::time::sleep(tokio::time::Duration::from_secs(self.config.retry_delay)).await;
println!("🔄 重试等待结束,准备下一次尝试");
} else {
println!("💔 已达到最大重试次数,放弃重试");
} }
} }
} }
@ -367,39 +377,114 @@ impl GeminiService {
client_config: &ClientConfig, client_config: &ClientConfig,
request_data: &GenerateContentRequest, request_data: &GenerateContentRequest,
) -> Result<GeminiResponse> { ) -> Result<GeminiResponse> {
println!("🌐 准备发送HTTP请求...");
println!("📍 请求URL: {}", url);
println!("⏱️ 超时时间: {}", self.config.timeout);
let mut request_builder = self.client let mut request_builder = self.client
.post(url) .post(url)
.timeout(tokio::time::Duration::from_secs(self.config.timeout)) .timeout(tokio::time::Duration::from_secs(self.config.timeout))
.json(request_data); .json(request_data);
// 添加请求头 // 添加请求头并记录日志
println!("📋 添加请求头:");
for (key, value) in &client_config.headers { for (key, value) in &client_config.headers {
println!(" {}: {}", key, if key == "Authorization" {
format!("Bearer {}...", &value[7..std::cmp::min(27, value.len())])
} else {
value.clone()
});
request_builder = request_builder.header(key, value); request_builder = request_builder.header(key, value);
} }
// 记录请求体信息
println!("📦 请求体信息:");
println!(" Content-Type: application/json");
println!(" Body size: {} bytes", serde_json::to_string(request_data).unwrap_or_default().len());
// 记录请求体内容(截断显示)
let request_json = serde_json::to_string_pretty(request_data).unwrap_or_default();
let preview_len = std::cmp::min(1000, request_json.len());
println!("📄 请求体预览 (前{}字符):", preview_len);
println!("{}", &request_json[..preview_len]);
if request_json.len() > 1000 {
println!(" ... (请求体已截断,总长度: {} 字符)", request_json.len());
}
println!("🚀 发送HTTP请求...");
let response = request_builder.send().await?; let response = request_builder.send().await?;
let status = response.status(); let status = response.status();
let headers = response.headers().clone(); let headers = response.headers().clone();
println!("📥 生成响应状态: {}", status); println!("📥 HTTP响应接收完成");
println!("📋 生成响应头: {:?}", headers); println!("📊 响应状态: {} {}", status.as_u16(), status.canonical_reason().unwrap_or("Unknown"));
println!("📋 响应头详情:");
for (name, value) in headers.iter() {
println!(" {}: {}", name, value.to_str().unwrap_or("<binary>"));
}
// 记录响应大小
if let Some(content_length) = headers.get("content-length") {
println!("📏 响应大小: {} bytes", content_length.to_str().unwrap_or("unknown"));
}
if !status.is_success() { if !status.is_success() {
println!("❌ HTTP请求失败状态码: {}", status);
let error_text = response.text().await.unwrap_or_default(); let error_text = response.text().await.unwrap_or_default();
println!("❌ 生成失败响应体: {}", error_text); println!("📄 错误响应体长度: {} 字符", error_text.len());
println!("📄 错误响应体内容:");
println!("{}", error_text);
// 尝试解析错误响应为JSON
if let Ok(error_json) = serde_json::from_str::<serde_json::Value>(&error_text) {
println!("🔍 解析后的错误JSON:");
println!("{}", serde_json::to_string_pretty(&error_json).unwrap_or_default());
}
return Err(anyhow!("API请求失败: {} - {}", status, error_text)); return Err(anyhow!("API请求失败: {} - {}", status, error_text));
} }
let response_text = response.text().await?; let response_text = response.text().await?;
println!("📄 生成成功响应: {}", response_text); println!("✅ HTTP请求成功");
println!("📄 响应体长度: {} 字符", response_text.len());
// 显示响应体预览
let preview_len = std::cmp::min(2000, response_text.len());
println!("📄 响应体预览 (前{}字符):", preview_len);
println!("{}", &response_text[..preview_len]);
if response_text.len() > 2000 {
println!(" ... (响应体已截断,总长度: {} 字符)", response_text.len());
}
println!("🔍 开始解析JSON响应...");
let gemini_response: GeminiResponse = serde_json::from_str(&response_text) let gemini_response: GeminiResponse = serde_json::from_str(&response_text)
.map_err(|e| anyhow!("解析生成响应失败: {} - 响应内容: {}", e, response_text))?; .map_err(|e| {
println!("❌ JSON解析失败: {}", e);
println!("📄 完整响应内容: {}", response_text);
anyhow!("解析生成响应失败: {} - 响应内容: {}", e, response_text)
})?;
println!("✅ JSON解析成功");
println!("📊 候选结果数量: {}", gemini_response.candidates.len());
if gemini_response.candidates.is_empty() { if gemini_response.candidates.is_empty() {
println!("❌ API返回的候选结果为空");
return Err(anyhow!("API返回结果为空")); return Err(anyhow!("API返回结果为空"));
} }
// 记录第一个候选结果的信息
if let Some(first_candidate) = gemini_response.candidates.first() {
println!("📝 第一个候选结果的部分数量: {}", first_candidate.content.parts.len());
if let Some(first_part) = first_candidate.content.parts.first() {
let text_preview = if first_part.text.len() > 200 {
format!("{}...", &first_part.text[..200])
} else {
first_part.text.clone()
};
println!("📝 第一个部分内容预览: {}", text_preview);
}
}
Ok(gemini_response) Ok(gemini_response)
} }