Harden patrol delete logging
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
@@ -38,6 +39,15 @@ def _new_trace_id(prefix: str) -> str:
|
||||
return f"{prefix}-{int(time.time() * 1000) % 1000000:06d}"
|
||||
|
||||
|
||||
def _safe_log_text(value: Any, limit: int = 3000) -> str:
|
||||
text = "" if value is None else str(value)
|
||||
text = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f]", " ", text)
|
||||
if len(text) > limit:
|
||||
text = text[: limit - 3] + "..."
|
||||
encoding = getattr(getattr(sys, "stderr", None), "encoding", None) or "utf-8"
|
||||
return text.encode(encoding, errors="backslashreplace").decode(encoding, errors="replace")
|
||||
|
||||
|
||||
def _load_patrol_delete_script(name: str) -> str:
|
||||
return (SCRIPT_DIR / name).read_text(encoding="utf-8")
|
||||
|
||||
@@ -207,7 +217,10 @@ class InventoryManage(AmamzonBase):
|
||||
rows = self._wait_listing_status_section_rows()
|
||||
parsed_rows = self._parse_listing_status_section_rows(rows)
|
||||
if not parsed_rows:
|
||||
logger.info(f"trace_id={trace_id} 商品状态统计读取为空: raw_rows={json.dumps(rows, ensure_ascii=False)}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 商品状态统计读取为空: "
|
||||
f"raw_rows={_safe_log_text(json.dumps(rows, ensure_ascii=False))}"
|
||||
)
|
||||
raise RuntimeError(f"未读取到商品状态统计标签: {rows}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 商品状态统计读取完成: "
|
||||
@@ -356,13 +369,16 @@ class InventoryManage(AmamzonBase):
|
||||
if not option_rows:
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 商品状态下拉选项为空: "
|
||||
f"open_result={json.dumps(open_result, ensure_ascii=False)}"
|
||||
f"open_result={_safe_log_text(json.dumps(open_result, ensure_ascii=False))}"
|
||||
)
|
||||
raise RuntimeError(f"商品状态下拉框已打开但未读取到选项: {open_result}")
|
||||
|
||||
result = self._run_js(LISTING_STATUS_SELECT_OPTION_SCRIPT, {"status": normalized_status}) or {}
|
||||
if not result.get("ok"):
|
||||
logger.info(f"trace_id={trace_id} 商品状态选项未命中: status={normalized_status}, result={result}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 商品状态选项未命中: "
|
||||
f"status={normalized_status}, result={_safe_log_text(result)}"
|
||||
)
|
||||
raise RuntimeError(f"未找到商品状态选项[{normalized_status}]: {result}")
|
||||
time.sleep(LISTING_STATUS_SELECT_DELAY)
|
||||
self._wait_inventory_loader()
|
||||
@@ -413,7 +429,7 @@ class InventoryManage(AmamzonBase):
|
||||
target = self._summarize_inventory_row(row)
|
||||
select_result = self._run_js(INVENTORY_SELECT_ALL_SCRIPT) or {}
|
||||
if not select_result.get("ok"):
|
||||
logger.info(f"trace_id={trace_id} 全选商品失败: status={status}, result={select_result}")
|
||||
logger.info(f"trace_id={trace_id} 全选商品失败: status={status}, result={_safe_log_text(select_result)}")
|
||||
raise RuntimeError(f"状态[{status}]全选商品失败: {select_result}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 当前筛选结果已全选: status={status}, "
|
||||
@@ -427,21 +443,27 @@ class InventoryManage(AmamzonBase):
|
||||
if delete_result.get("ok"):
|
||||
break
|
||||
if delete_result.get("menuOpened"):
|
||||
logger.info(f"trace_id={trace_id} 状态[{status}]已点击选择组操作,等待删除菜单展开: {delete_result}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 状态[{status}]已点击选择组操作,等待删除菜单展开: "
|
||||
f"{_safe_log_text(delete_result)}"
|
||||
)
|
||||
time.sleep(1)
|
||||
continue
|
||||
logger.info(f"trace_id={trace_id} 状态[{status}]第{attempt + 1}次点击批量删除未命中: {delete_result}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 状态[{status}]第{attempt + 1}次点击批量删除未命中: "
|
||||
f"{_safe_log_text(delete_result)}"
|
||||
)
|
||||
if not delete_result.get("ok"):
|
||||
logger.info(f"trace_id={trace_id} 点击批量删除失败: status={status}, result={delete_result}")
|
||||
logger.info(f"trace_id={trace_id} 点击批量删除失败: status={status}, result={_safe_log_text(delete_result)}")
|
||||
raise RuntimeError(f"状态[{status}]点击批量删除失败: {delete_result}")
|
||||
logger.info(f"trace_id={trace_id} 批量删除按钮点击成功: status={status}, result={delete_result}")
|
||||
logger.info(f"trace_id={trace_id} 批量删除按钮点击成功: status={status}, result={_safe_log_text(delete_result)}")
|
||||
|
||||
self._confirm_delete_modal(status, trace_id=trace_id)
|
||||
success_message = self._wait_delete_success_message(status, trace_id=trace_id)
|
||||
deleted_count = self._extract_delete_success_count(success_message) or int(select_result.get("rowCount") or 1)
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 批量删除确认完成: status={status}, "
|
||||
f"deleted_count={deleted_count}, success_message={success_message}"
|
||||
f"deleted_count={deleted_count}, success_message={_safe_log_text(success_message)}"
|
||||
)
|
||||
return {
|
||||
"deletedCount": deleted_count,
|
||||
@@ -472,10 +494,13 @@ class InventoryManage(AmamzonBase):
|
||||
trace_id = trace_id or _new_trace_id("modal")
|
||||
js_result = self._click_confirm_delete_modal_with_js()
|
||||
if js_result.get("ok"):
|
||||
logger.info(f"trace_id={trace_id} 已通过 JS 确认删除弹窗: status={status}, result={js_result}")
|
||||
logger.info(f"trace_id={trace_id} 已通过 JS 确认删除弹窗: status={status}, result={_safe_log_text(js_result)}")
|
||||
return
|
||||
|
||||
logger.info(f"trace_id={trace_id} JS 确认删除弹窗未命中,尝试驱动点击: status={status}, result={js_result}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} JS 确认删除弹窗未命中,尝试驱动点击: "
|
||||
f"status={status}, result={_safe_log_text(js_result)}"
|
||||
)
|
||||
confirm_button = self.tab.ele(
|
||||
'xpath://kat-modal[@data-testid="action-modal"]//kat-button[@variant="primary"]',
|
||||
timeout=5,
|
||||
@@ -507,10 +532,13 @@ class InventoryManage(AmamzonBase):
|
||||
if text not in seen_messages:
|
||||
seen_messages.append(text)
|
||||
if self._is_delete_success_message(text):
|
||||
logger.info(f"trace_id={trace_id} 读取到删除成功提示: status={status}, message={text}")
|
||||
logger.info(f"trace_id={trace_id} 读取到删除成功提示: status={status}, message={_safe_log_text(text)}")
|
||||
return text
|
||||
time.sleep(0.3)
|
||||
logger.info(f"trace_id={trace_id} 删除后未读取到成功提示: status={status}, seen_messages={seen_messages}")
|
||||
logger.info(
|
||||
f"trace_id={trace_id} 删除后未读取到成功提示: "
|
||||
f"status={status}, seen_messages={_safe_log_text(seen_messages)}"
|
||||
)
|
||||
raise RuntimeError("删除后未读取到成功提示")
|
||||
|
||||
def _collect_delete_success_messages(self) -> List[str]:
|
||||
@@ -1260,7 +1288,7 @@ class PatrolDeleteTask:
|
||||
|
||||
def log(self, message: str, level: str = "INFO"):
|
||||
level_name = str(level or "INFO").upper()
|
||||
logger.log(level_name, f"[ProductTask] {message}")
|
||||
logger.log(level_name, f"[PatrolDeleteTask] {_safe_log_text(message)}")
|
||||
|
||||
def process_task(self, task_data: dict):
|
||||
"""处理巡店删除任务主入口。"""
|
||||
@@ -1658,7 +1686,7 @@ class PatrolDeleteTask:
|
||||
try:
|
||||
self.log(f"trace_id={trace_id} 尝试回传巡店删除结果 (第 {retry + 1}/{max_retries} 次)")
|
||||
self.log(f"trace_id={trace_id} 回传URL: {url}")
|
||||
self.log(f"trace_id={trace_id} 回传数据: {payload}")
|
||||
self.log(f"trace_id={trace_id} 回传数据: {_safe_log_text(payload)}")
|
||||
response = requests.post(
|
||||
url,
|
||||
json=payload,
|
||||
@@ -1666,7 +1694,7 @@ class PatrolDeleteTask:
|
||||
timeout=30,
|
||||
verify=False,
|
||||
)
|
||||
self.log(f"trace_id={trace_id} 回传结果: {response.text}")
|
||||
self.log(f"trace_id={trace_id} 回传结果: {_safe_log_text(response.text)}")
|
||||
try:
|
||||
response_data = response.json()
|
||||
except (AttributeError, ValueError):
|
||||
@@ -1674,13 +1702,14 @@ class PatrolDeleteTask:
|
||||
api_success = not (isinstance(response_data, dict) and response_data.get("success") is False)
|
||||
self.log(
|
||||
f"trace_id={trace_id} 巡店删除结果回传响应: status_code={response.status_code}, "
|
||||
f"api_success={api_success}, response={response.text}"
|
||||
f"api_success={api_success}, response={_safe_log_text(response.text)}"
|
||||
)
|
||||
if response.status_code == 200 and api_success:
|
||||
self.log(f"trace_id={trace_id} 巡店删除结果回传成功: {shop_name}")
|
||||
return
|
||||
self.log(
|
||||
f"trace_id={trace_id} 巡店删除结果回传失败,状态码: {response.status_code}, 响应: {response.text}",
|
||||
f"trace_id={trace_id} 巡店删除结果回传失败,状态码: {response.status_code}, "
|
||||
f"响应: {_safe_log_text(response.text)}",
|
||||
"WARNING",
|
||||
)
|
||||
except Exception as exc:
|
||||
|
||||
Reference in New Issue
Block a user