From 4e6837251801beed1b7e290798e3751f5eb37a64 Mon Sep 17 00:00:00 2001 From: sansen Date: Wed, 23 Sep 2026 17:42:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=94=B9=E4=B8=BA=E6=91=98?= =?UTF-8?q?=E8=A6=81=20+=20=E6=9C=89=E7=95=8C=E9=A2=84=E8=A7=88=EF=BC=9A?= =?UTF-8?q?=E5=8D=95=E6=AC=A1=E8=AF=B7=E6=B1=82=E6=97=A5=E5=BF=97=206940KB?= =?UTF-8?q?=20=E2=86=92=202.8KB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /convert/start 原先 logger.info 直接 dump 整份结果(json.dumps(indent=2)):实测 1MB 输入 → 20188 条 → 6.9MB 日志,是原文的 15%,indent 还要再乘 1.4。转几份族谱 日志文件就会被撑爆。 改为: - 一行摘要:输入字数、结果条数、类型分布、耗时(格式与 batch 接口的日志保持一致) - 前 LOG_PREVIEW_ITEMS(=10) 条结果预览,体积有硬上界 - 新增 _result_summary() helper 类型分布一行能看出解析形态(如 {'干支纪年': 15624, '古代纪年': 147, ...}), 排查"整批变成未匹配"这类回归比翻全量结果还快。明细请用接口返回值。 验证:单次 1MB 请求日志 2.8KB(降 2428x);/convert/start、/convert/batch、 403 鉴权、空文本四条路径均正常;pytest 260 passed。 Co-Authored-By: Claude Code --- client_app.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/client_app.py b/client_app.py index 896f527..cbbaa06 100644 --- a/client_app.py +++ b/client_app.py @@ -1,4 +1,5 @@ import json +from collections import Counter from time import perf_counter from fastapi import FastAPI, HTTPException, Header, Request from fastapi.responses import JSONResponse @@ -20,12 +21,26 @@ app.add_middleware( # batch 接口单次请求的条目上限(防滥用) BATCH_MAX_ITEMS = 1000 +# 日志里最多预览多少条结果。完整结果序列化后体积可达数 MB +# (实测 1MB 输入 → 20188 条 → 6.9MB JSON,是原文的 15%,含缩进还要再乘 1.4), +# 全量落盘会迅速撑爆日志文件。 +LOG_PREVIEW_ITEMS = 10 + def _check_auth(Authorization: str): if Authorization != "3FFA6A4B073CF065969630692331A873": raise HTTPException(status_code=403, detail="未授权的操作") +def _result_summary(res: list) -> str: + """一行摘要:结果条数 + 类型分布(如 {'古代纪年': 12, '干支纪年': 3})。 + + /convert/start 的日志只记摘要与有界预览,不记全量结果——看明细请用接口返回值。 + """ + kinds = Counter(r["类型"] for r in res) + return f"{len(res)} 条, 类型分布 {dict(kinds)}" + + def _parse_urlencoded_content(body: bytes) -> str: """手动解析 x-www-form-urlencoded 的 content 字段:绕过 starlette 1MB 表单限制""" from urllib.parse import parse_qs @@ -47,8 +62,15 @@ async def convert_str( try: content = _parse_urlencoded_content(await request.body()) + t0 = perf_counter() res = convert_text(content) - logger.info(f"转换结果: {json.dumps(res, ensure_ascii=False, indent=2)}") + dt = perf_counter() - t0 + # 只记摘要 + 前 N 条预览(格式与 batch 接口的日志保持一致) + logger.info(f"转换完成: 输入 {len(content)} 字, {_result_summary(res)}, " + f"耗时 {dt * 1000:.0f}ms") + if res: + head = res[:LOG_PREVIEW_ITEMS] + logger.info(f"结果前 {len(head)} 条: {json.dumps(head, ensure_ascii=False)}") return JSONResponse(content={"code": 0, "result": res}) except Exception as e: logger.error(f"转换异常: {str(e)}")