logging: 全链路日志与完整异常堆栈
- 新增 logutil:DEBUG 全量滚动日志文件 + 控制台 INFO 简洁输出 + GUI 队列处理器 - providers:每次尝试失败记录 HTTP 状态/响应体,网络异常 logger.exception 留完整堆栈 - pipeline:单任务异常不拖垮整批,缓存命中/阶段耗时/停止过程全程留痕 - CLI/GUI 顶层兜底:未预期异常打印完整 traceback 并指引日志文件;GUI 新增「打开日志」按钮 - 新增 test_logutil(文件落盘/级别过滤/异常堆栈/队列),共 33 个测试全部通过
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
@@ -15,6 +16,8 @@ import aiohttp
|
||||
|
||||
from .config import AppConfig
|
||||
|
||||
logger = logging.getLogger("violation_detector.providers")
|
||||
|
||||
MIME = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
|
||||
".webp": "image/webp", ".gif": "image/gif", ".bmp": "image/bmp",
|
||||
".tiff": "image/tiff"}
|
||||
@@ -114,6 +117,7 @@ async def detect_ark(session, sem, cfg: AppConfig, prompt: str, path: str, stop=
|
||||
last_err = ""
|
||||
for attempt in range(1, cfg.retries + 1):
|
||||
if stop and stop():
|
||||
logger.info("豆包检测 %s:用户停止", fname)
|
||||
return {"file": fname, "provider": "doubao", "status": "error", "attr": "",
|
||||
"logic": "", "category": "检测异常", "raw": "用户停止", "usage": {}}
|
||||
try:
|
||||
@@ -123,11 +127,17 @@ async def detect_ark(session, sem, cfg: AppConfig, prompt: str, path: str, stop=
|
||||
data = await r.json()
|
||||
content = data["choices"][0]["message"]["content"]
|
||||
return _result(fname, "doubao", content, data)
|
||||
last_err = f"HTTP {r.status}: {(await r.text())[:300]}"
|
||||
except Exception as e: # noqa: BLE001
|
||||
last_err = f"{type(e).__name__}: {e}"
|
||||
body = (await r.text())[:2000]
|
||||
last_err = f"HTTP {r.status}: {body[:300]}"
|
||||
logger.warning("豆包检测 %s 第%d/%d次尝试失败:HTTP %s\n响应体:%s",
|
||||
fname, attempt, cfg.retries, r.status, body)
|
||||
except Exception: # noqa: BLE001 网络层异常:记录完整堆栈后重试
|
||||
last_err = "网络/协议异常(详见日志)"
|
||||
logger.exception("豆包检测 %s 第%d/%d次尝试抛出异常", fname, attempt, cfg.retries)
|
||||
if attempt < cfg.retries:
|
||||
logger.info("豆包检测 %s:%.0f 秒后重试", fname, 3 * attempt)
|
||||
await asyncio.sleep(3 * attempt)
|
||||
logger.error("豆包检测 %s 最终失败:%s", fname, last_err)
|
||||
return {"file": fname, "provider": "doubao", "status": "error", "attr": "",
|
||||
"logic": "", "category": "检测异常", "raw": last_err, "usage": {}}
|
||||
|
||||
@@ -156,6 +166,7 @@ async def detect_deepseek(session, sem, cfg: AppConfig, prompt: str, path: str,
|
||||
last_err = ""
|
||||
for attempt in range(1, cfg.retries + 1):
|
||||
if stop and stop():
|
||||
logger.info("DeepSeek 检测 %s:用户停止", fname)
|
||||
return {"file": fname, "provider": "deepseek", "status": "error", "attr": "",
|
||||
"logic": "", "category": "检测异常", "raw": "用户停止", "usage": {}}
|
||||
try:
|
||||
@@ -167,12 +178,22 @@ async def detect_deepseek(session, sem, cfg: AppConfig, prompt: str, path: str,
|
||||
if content and content.strip():
|
||||
return _result(fname, "deepseek", content, data)
|
||||
# 推理烧尽预算会得到空正文,按可重试错误处理
|
||||
last_err = "empty content (reasoning exhausted max_tokens?)"
|
||||
fr = data["choices"][0].get("finish_reason")
|
||||
last_err = f"empty content (finish_reason={fr}, max_tokens={cfg.max_tokens})"
|
||||
logger.warning("DeepSeek 检测 %s 第%d/%d次尝试返回空正文"
|
||||
"(finish_reason=%s,推理可能耗尽 max_tokens=%s)",
|
||||
fname, attempt, cfg.retries, fr, cfg.max_tokens)
|
||||
else:
|
||||
last_err = f"HTTP {r.status}: {(await r.text())[:300]}"
|
||||
except Exception as e: # noqa: BLE001
|
||||
last_err = f"{type(e).__name__}: {e}"
|
||||
body = (await r.text())[:2000]
|
||||
last_err = f"HTTP {r.status}: {body[:300]}"
|
||||
logger.warning("DeepSeek 检测 %s 第%d/%d次尝试失败:HTTP %s\n响应体:%s",
|
||||
fname, attempt, cfg.retries, r.status, body)
|
||||
except Exception: # noqa: BLE001 网络层异常:记录完整堆栈后重试
|
||||
last_err = "网络/协议异常(详见日志)"
|
||||
logger.exception("DeepSeek 检测 %s 第%d/%d次尝试抛出异常", fname, attempt, cfg.retries)
|
||||
if attempt < cfg.retries:
|
||||
logger.info("DeepSeek 检测 %s:%.0f 秒后重试", fname, 3 * attempt)
|
||||
await asyncio.sleep(3 * attempt)
|
||||
logger.error("DeepSeek 检测 %s 最终失败:%s", fname, last_err)
|
||||
return {"file": fname, "provider": "deepseek", "status": "error", "attr": "",
|
||||
"logic": "", "category": "检测异常", "raw": last_err, "usage": {}}
|
||||
|
||||
Reference in New Issue
Block a user