add excel failure alert log with error digest
This commit is contained in:
parent
c382665753
commit
fa631100ba
@ -14,6 +14,7 @@ import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import uuid
|
||||
@ -328,6 +329,16 @@ class OpenClawDingTalkBot(ChatbotHandler):
|
||||
10,
|
||||
min(int(os.getenv("EXCEL_TEXT_PROMPT_COOLDOWN_SECONDS", "120")), 600),
|
||||
)
|
||||
self.excel_alert_log_enabled = bool_env("EXCEL_ALERT_LOG_ENABLED", True)
|
||||
self.excel_alert_log_path = (
|
||||
os.getenv(
|
||||
"EXCEL_ALERT_LOG_PATH",
|
||||
"/opt/openclaw-dingtalk-bridge/logs/excel_converter_alerts.log",
|
||||
).strip()
|
||||
or "/opt/openclaw-dingtalk-bridge/logs/excel_converter_alerts.log"
|
||||
)
|
||||
self.excel_alert_detail_limit = max(200, min(int(os.getenv("EXCEL_ALERT_DETAIL_LIMIT", "1600")), 10000))
|
||||
self._excel_alert_log_lock = threading.Lock()
|
||||
self._recent_excel_success_ts = {}
|
||||
|
||||
def _should_handle(self, msg: ChatbotMessage, text: str) -> bool:
|
||||
@ -2253,6 +2264,71 @@ class OpenClawDingTalkBot(ChatbotHandler):
|
||||
self.logger.exception("upload excel output to s3 failed: %s", exc)
|
||||
return ""
|
||||
|
||||
def _excel_error_summary(self, detail: str) -> str:
|
||||
raw = str(detail or "").strip()
|
||||
if not raw:
|
||||
return "unknown_error"
|
||||
lines = [line.strip() for line in raw.splitlines() if line.strip()]
|
||||
if not lines:
|
||||
return raw[:300]
|
||||
for line in reversed(lines):
|
||||
lower_line = line.lower()
|
||||
if lower_line.startswith("traceback"):
|
||||
continue
|
||||
if lower_line.startswith("file "):
|
||||
continue
|
||||
if lower_line in {"^^^^^^", "^^^^^"}:
|
||||
continue
|
||||
return line[:300]
|
||||
return lines[-1][:300]
|
||||
|
||||
def _record_excel_failure_alert(
|
||||
self,
|
||||
msg: ChatbotMessage,
|
||||
file_name: str,
|
||||
stage: str,
|
||||
detail: str,
|
||||
return_code: int | None = None,
|
||||
stdout_text: str = "",
|
||||
stderr_text: str = "",
|
||||
) -> None:
|
||||
normalized_detail = str(detail or "").strip() or "unknown_error"
|
||||
summary = self._excel_error_summary(normalized_detail)
|
||||
digest = hashlib.sha1(normalized_detail.encode("utf-8", errors="ignore")).hexdigest()[:12]
|
||||
log_record = {
|
||||
"ts": dt.datetime.now().isoformat(timespec="seconds"),
|
||||
"event": "excel_convert_failed",
|
||||
"stage": stage,
|
||||
"digest": digest,
|
||||
"summary": summary,
|
||||
"return_code": return_code,
|
||||
"file_name": str(file_name or ""),
|
||||
"conversation_id": str(getattr(msg, "conversation_id", "") or ""),
|
||||
"session_webhook": str(getattr(msg, "session_webhook", "") or ""),
|
||||
"sender_staff_id": str(getattr(msg, "sender_staff_id", "") or ""),
|
||||
"detail": normalized_detail[: self.excel_alert_detail_limit],
|
||||
"stderr": str(stderr_text or "")[: self.excel_alert_detail_limit],
|
||||
"stdout": str(stdout_text or "")[: self.excel_alert_detail_limit],
|
||||
}
|
||||
self.logger.warning(
|
||||
"excel failure alert stage=%s digest=%s file=%s summary=%s",
|
||||
stage,
|
||||
digest,
|
||||
file_name,
|
||||
summary,
|
||||
)
|
||||
if not self.excel_alert_log_enabled:
|
||||
return
|
||||
try:
|
||||
parent_dir = os.path.dirname(self.excel_alert_log_path) or "."
|
||||
os.makedirs(parent_dir, exist_ok=True)
|
||||
line = json.dumps(log_record, ensure_ascii=False)
|
||||
with self._excel_alert_log_lock:
|
||||
with open(self.excel_alert_log_path, "a", encoding="utf-8") as file_obj:
|
||||
file_obj.write(line + "\n")
|
||||
except Exception:
|
||||
self.logger.exception("write excel alert log failed")
|
||||
|
||||
def _run_excel_image_link_job(self, msg: ChatbotMessage, file_payload: dict) -> tuple[str, bool]:
|
||||
if not self.excel_link_feature_enabled:
|
||||
return "Excel 图片链接转图片功能未启用。", False
|
||||
@ -2282,6 +2358,12 @@ class OpenClawDingTalkBot(ChatbotHandler):
|
||||
fh.write(response.content)
|
||||
except Exception as exc:
|
||||
self.logger.exception("download incoming excel failed")
|
||||
self._record_excel_failure_alert(
|
||||
msg,
|
||||
file_name,
|
||||
stage="download_source_excel",
|
||||
detail=f"{type(exc).__name__}: {exc}",
|
||||
)
|
||||
return f"下载源文件失败:{exc}", False
|
||||
|
||||
cmd = [
|
||||
@ -2312,6 +2394,12 @@ class OpenClawDingTalkBot(ChatbotHandler):
|
||||
timeout=self.excel_converter_timeout,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
self._record_excel_failure_alert(
|
||||
msg,
|
||||
file_name,
|
||||
stage="excel_converter_timeout",
|
||||
detail=f"timeout>{self.excel_converter_timeout}s",
|
||||
)
|
||||
return f"Excel 转换超时(>{self.excel_converter_timeout}秒),请稍后重试。", False
|
||||
|
||||
stdout_text = (proc.stdout or "").strip()
|
||||
@ -2319,6 +2407,15 @@ class OpenClawDingTalkBot(ChatbotHandler):
|
||||
if proc.returncode != 0 or not os.path.exists(output_path):
|
||||
detail = stderr_text or stdout_text or "未知错误"
|
||||
self.logger.error("excel converter failed code=%s detail=%s", proc.returncode, detail[:2500])
|
||||
self._record_excel_failure_alert(
|
||||
msg,
|
||||
file_name,
|
||||
stage="excel_converter_failed",
|
||||
detail=detail,
|
||||
return_code=proc.returncode,
|
||||
stdout_text=stdout_text,
|
||||
stderr_text=stderr_text,
|
||||
)
|
||||
return f"Excel 转换失败:{detail[:1200]}", False
|
||||
|
||||
summary_line = ""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user