fix(quality): 质量检查引用已删除的 MatchStats.id 必然 500 + 检查无日志
生产实测: POST /admin/data-quality/run 100% 失败,且日志无任何记录。 根因链: 1. P0-02 把 MatchStats 主键改为 match_id(无 id 属性),但质量检查 查询仍写 MatchStats.id.is_(None) → AttributeError → 500 2. handler 无 logger 调用;未捕获异常走 uvicorn.error(默认 propagate=False),不经过 root handler → 内存日志页/文件日志 都看不到 traceback,排障无据可查 修复: - MatchStats.id → MatchStats.match_id(与 P0-02 模型对齐) - 成功路径记 info 日志(检查名=通过/未通过(计数)) - setup_logging 打开 uvicorn/uvicorn.error 的 propagate, 未捕获异常 traceback 进入内存缓冲与滚动文件 - 回归测试 3 例(mock session):修复前红(3 failed),修复后绿; 全量 329 passed 8 skipped 零回归
This commit is contained in:
@@ -234,13 +234,14 @@ async def run_data_quality_check(db: AsyncSession = Depends(get_db_read)):
|
||||
checks = []
|
||||
|
||||
# 检查1: 已完赛但无统计的比赛
|
||||
# 注意: MatchStats 主键是 match_id(P0-02),不是 id —— 引用 .id 会 AttributeError
|
||||
finished_no_stats = (
|
||||
await db.execute(
|
||||
select(func.count())
|
||||
.select_from(Match)
|
||||
.outerjoin(MatchStats, Match.id == MatchStats.match_id)
|
||||
.where(Match.match_status == "finished")
|
||||
.where(MatchStats.id.is_(None))
|
||||
.where(MatchStats.match_id.is_(None))
|
||||
)
|
||||
).scalar() or 0
|
||||
|
||||
@@ -276,6 +277,13 @@ async def run_data_quality_check(db: AsyncSession = Depends(get_db_read)):
|
||||
db.add(c)
|
||||
await db.commit()
|
||||
|
||||
# 成功路径留痕:检查何时跑过、各项结果如何(此前 handler 无任何日志,
|
||||
# 加上未捕获异常走 uvicorn.error 不进内存缓冲,线上排障无据可查)
|
||||
logger.info(
|
||||
"数据质量检查完成: %s",
|
||||
"; ".join(f"{c.check_name}={'通过' if c.passed else '未通过'}({c.actual_value:.0f})" for c in checks),
|
||||
)
|
||||
|
||||
return {"ok": True, "checks": [{"name": c.check_name, "passed": c.passed} for c in checks]}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user