# -*- coding: utf-8 -*- """分析 v8 执行结果,提取每个任务的成功/失败状态。""" import json import re from pathlib import Path from dotenv import load_dotenv load_dotenv(Path(__file__).resolve().parents[2] / ".env") from _env_paths import get_output_path log_dir = get_output_path("SYSTEM_LOG_ROOT") raw = json.loads((log_dir / "2026-02-21__etl_run_raw_v8.json").read_text("utf-8")) error_log = raw.get("error_log", "") output_log = raw.get("output_log", "") full = output_log + "\n" + error_log # 提取任务结果 success_pat = re.compile(r"任务 (\S+) 执行成功") fail_pat = re.compile(r"任务 (\S+) 失败[::]?\s*(.*)") skip_pat = re.compile(r"跳过 (\S+)") successes = success_pat.findall(full) failures = [(m.group(1), m.group(2)[:120]) for m in fail_pat.finditer(full)] skips = skip_pat.findall(full) # 去重 seen_s = set() unique_successes = [] for s in successes: if s not in seen_s: seen_s.add(s) unique_successes.append(s) seen_f = set() unique_failures = [] for task, reason in failures: if task not in seen_f: seen_f.add(task) unique_failures.append((task, reason)) print(f"=== v8 执行结果分析 ===") print(f"成功: {len(unique_successes)} 个") for s in unique_successes: print(f" ✅ {s}") print(f"\n失败: {len(unique_failures)} 个") for task, reason in unique_failures: short = reason.split("\n")[0][:100] print(f" ❌ {task}: {short}") # 查找首个非级联错误 first_error_pat = re.compile(r"ERROR.*?(?:错误|Error|exception|Traceback)", re.IGNORECASE) in_failed_count = error_log.count("InFailedSqlTransaction") print(f"\nInFailedSqlTransaction 出现次数: {in_failed_count}") # 查找根因错误(非 InFailedSqlTransaction 的 ERROR) error_lines = [l for l in error_log.split("\n") if "ERROR" in l and "InFailedSqlTransaction" not in l] print(f"\n非级联 ERROR 行 ({len(error_lines)} 行):") for line in error_lines[:20]: print(f" {line.strip()[:150]}")