diff --git a/flows/monitor/alert_failure.py b/flows/monitor/alert_failure.py index 4f7c975..14e8058 100644 --- a/flows/monitor/alert_failure.py +++ b/flows/monitor/alert_failure.py @@ -102,11 +102,11 @@ def wecom_alert_failure(event: dict | str | None = None) -> dict: ended = detail.get("end_time") or detail.get("expected_start_time") occurred = occurred or ended - lines = [f"## 🔴 流程失败:{flow_name or resource_name or '未知'}"] + lines = [f"## 流程失败:{flow_name or resource_name or '未知'}"] if run_name: - lines.append(f"> Run「{run_name}」 · {event_name.split('.')[-1]} · {_fmt_ts(occurred)}") + lines.append(f"> Run {run_name} · {event_name.split('.')[-1]} · {_fmt_ts(occurred)}") if state_msg: - lines.append(f"> 错误:{state_msg[:150].replace(chr(10), ' ')}") + lines.append(f'> 错误:{state_msg[:150].replace(chr(10), " ")}') if run_id: lines.append(f"> [查看详情]({UI_BASE}/runs/flow-run/{run_id})") else: diff --git a/flows/monitor/daily_report.py b/flows/monitor/daily_report.py index 41d5e4d..7e078b1 100644 --- a/flows/monitor/daily_report.py +++ b/flows/monitor/daily_report.py @@ -40,9 +40,12 @@ def _system_lines(name: str, report: dict, goods: dict, lines: list[str]) -> boo g = goods or {} zero = g.get("zeroGoodsOrders", 0) - goods_txt = f"{g.get('goods', 0):,} 行" + (f"(缺 {zero:,})" if zero else "") - order_txt = f"订单 {remote_t:,} ✅" if ok else f"订单 远程 {remote_t:,} / 本地 {local_t:,} ⚠️" - lines.append(f"**{name}** {order_txt} · 商品 {goods_txt} {'✅' if not zero else '⚠️'}") + goods_txt = f"{g.get('goods', 0):,} 行" + (f'(缺 {zero:,})' if zero else "") + if ok: + order_txt = f"订单 {remote_t:,} 一致" + else: + order_txt = f"订单 远程 {remote_t:,} / 本地 {local_t:,} 不一致" + lines.append(f"**{name}** {order_txt} · 商品 {goods_txt}") diff_days = [d for d in days_r if not d.get("ok")] diff_units = sum(_affected_units(d.get("diff")) for d in diff_days) @@ -56,7 +59,7 @@ def build_daily_message( goods: dict, ocr_today: dict, ocr_pending: int, failures: list[dict], ) -> tuple[str, bool]: """拼装日报 markdown,返回 (消息, 是否需关注)。单行结论 + 引用详情的紧凑排版。""" - lines = [f"## 📊 数据核验日报 {datetime.now():%m-%d %H:%M}(近 {days} 天 {window})"] + lines = [f"## 数据核验日报 {datetime.now():%m-%d %H:%M}(近 {days} 天 {window})"] attention = False for name, report in (("RIIN", riin), ("SDS", sds)): @@ -67,24 +70,25 @@ def build_daily_message( attention = True processed, failed = (ocr_today or {}).get("processed", 0), (ocr_today or {}).get("failed", 0) - ocr_txt = f"**OCR 今日** 处理 {processed:,} · 识别失败 {failed:,}" + (" ✅" if not failed else " ⚠️") + ocr_txt = f"**OCR** 今日处理 {processed:,} · 识别失败 " + ocr_txt += f'{failed:,}' if failed else "0" if ocr_pending: - ocr_txt += f"(累计待处理 {ocr_pending:,})" + ocr_txt += f" · 待处理 {ocr_pending:,}" lines.append(ocr_txt) if failures: attention = True - lines.append(f"**失败任务(24h)** {len(failures)} 次 🔴") + lines.append(f'**任务** 失败 {len(failures)} 次(24h)') for f in failures[:6]: start = (f.get("start") or "")[5:] # MM-DD HH:MM - lines.append(f"> {f.get('flow', '?')}「{f.get('name', '?')}」{f.get('state', '?')} · {start}") + lines.append(f"> {f.get('flow', '?')}:{f.get('name', '?')} {f.get('state', '?')} {start}") if len(failures) > 6: lines.append(f"> …等共 {len(failures)} 次") else: - lines.append("**失败任务(24h)** 0 ✅") + lines.append("**任务** 失败 0 次(24h)") - lines.append('⚠️ 存在需关注项,见上' if attention - else '✅ 数据全部一致,无异常') + lines.append('存在需关注项,见上' if attention + else '数据全部一致,无异常') return "\n".join(lines), attention diff --git a/flows/monitor/device_check.py b/flows/monitor/device_check.py index 014a25a..107b710 100644 --- a/flows/monitor/device_check.py +++ b/flows/monitor/device_check.py @@ -291,11 +291,11 @@ def _check_services() -> dict: def _mark(pct: float | None, threshold: int) -> str: - """百分比展示:超阈值用 warning 色加粗+🔴。""" + """百分比展示:超阈值用 warning 色加粗。""" if pct is None: return "—" if pct >= threshold: - return f'**{pct:.0f}%** 🔴' + return f'**{pct:.0f}%**' return f"{pct:.0f}%" @@ -343,7 +343,7 @@ def device_check(alarm_threshold: int = 80) -> dict: print(f"[device-check] 磁盘检查失败: {err}") threshold = alarm_threshold - header = f"## 🖥 设备日报 {datetime.now():%m-%d %H:%M}(24h 采样 {agg['count']} 次" + header = f"## 设备日报 {datetime.now():%m-%d %H:%M}(24h 采样 {agg['count']} 次" if agg.get("firstTs"): first = datetime.fromisoformat(agg["firstTs"]) if first > datetime.now() - timedelta(hours=23): @@ -397,8 +397,12 @@ def device_check(alarm_threshold: int = 80) -> dict: else: mem_txt = "显存 无数据" temp_peak = g.get("tempPeak") - temp_txt = (f"温度峰 {temp_peak:.0f}°C" + (" 🔴过热" if temp_peak >= GPU_TEMP_WARN else " ✅") - if temp_peak is not None else "温度 无数据") + if temp_peak is None: + temp_txt = "温度 无数据" + elif temp_peak >= GPU_TEMP_WARN: + temp_txt = f'温度峰 {temp_peak:.0f}°C 过热' + else: + temp_txt = f"温度峰 {temp_peak:.0f}°C 正常" lines.append(f"**GPU** {name} {util_txt} | {mem_txt} | {temp_txt}") else: gpus_now = _check_gpus() @@ -415,22 +419,25 @@ def device_check(alarm_threshold: int = 80) -> dict: if docker.get("running") is None: docker_txt = issues[0]["issue"] if issues else "不可用" else: - docker_txt = f"运行 {docker['running']}/{docker.get('total', '?')} · 异常 {len(issues)}" + ("🔴" if issues else "") + n_issues = len(issues) + docker_txt = "运行 " + f"{docker['running']}/{docker.get('total', '?')} · 异常 " + docker_txt += f'{n_issues}' if n_issues else "0" if svc: - docker_txt += f" | OCR {'✅' if svc.get('ocr') else '🔴'} | PG {'✅' if svc.get('pg') else '🔴'}" + docker_txt += " · OCR " + ("正常" if svc.get("ocr") else '异常') + docker_txt += " · PG " + ("正常" if svc.get("pg") else '异常') lines.append(f"**Docker** {docker_txt}") for it in issues[:8]: - lines.append(f"> 🔴 {it['name']}:{it['issue']}") + lines.append(f"> {it['name']}:{it['issue']}") failures = checks.get("prefectFailures") or [] if failures: - lines.append(f"**失败任务(24h)** {len(failures)} 次 🔴") + lines.append(f'**任务** 失败 {len(failures)} 次(24h)') for f in failures[:5]: - lines.append(f"> {f['flow']}「{f['name']}」{f['state']} · {(f.get('start') or '')[5:]}") + lines.append(f"> {f['flow']}:{f['name']} {f['state']} {(f.get('start') or '')[5:]}") if len(failures) > 5: lines.append(f"> …共 {len(failures)} 次") else: - lines.append("**失败任务(24h)** 0 ✅") + lines.append("**任务** 失败 0 次(24h)") mem_peak_for_alarm = mem.get("peak") if mem else None swap_peak_for_alarm = swap.get("peak") if swap else None @@ -442,8 +449,8 @@ def device_check(alarm_threshold: int = 80) -> dict: or any((g.get("tempPeak") or 0) >= GPU_TEMP_WARN for g in gpu_stats) or bool(issues) or bool(failures) or not svc.get("ocr") or not svc.get("pg") ) - lines.append('🔴 有项目需要处理,见上' if alarms - else '✅ 一切正常') + lines.append('有项目需要处理,见上' if alarms + else '一切正常') content = "\n".join(lines) sent = send_markdown(content)