Preserve plugin diagnostics without degrading overall status

This commit is contained in:
jxxghp
2026-07-20 10:15:15 +08:00
parent d666134ed2
commit 405350c774
14 changed files with 270 additions and 23 deletions
+128
View File
@@ -23,6 +23,7 @@ def test_doctor_report_has_stable_json_shape(tmp_path, monkeypatch):
assert payload["environment"]["config_path"] == str(tmp_path)
assert isinstance(payload["summary"]["total"], int)
assert isinstance(payload["findings"], list)
assert all("affects_report_status" in item for item in payload["findings"])
assert any(item["id"] == "runtime.paths" for item in payload["findings"])
@@ -86,3 +87,130 @@ def test_doctor_accepts_healthy_unmanaged_backend_port(monkeypatch):
assert finding.severity == DoctorSeverity.Info
assert finding.context["backend_version"] == "v2-test"
assert runner.report.find("port.backend_occupied") is None
def test_doctor_plugin_log_error_does_not_degrade_report(tmp_path, monkeypatch):
"""插件独立日志中的错误应保留告警,但不降低系统整体状态。"""
monkeypatch.setattr(settings, "CONFIG_DIR", str(tmp_path))
plugin_log = settings.LOG_PATH / "plugins" / "demo.log"
plugin_log.parent.mkdir(parents=True, exist_ok=True)
plugin_log.write_text(
"【ERROR】2026-07-20 08:00:00 - demo.py - 插件任务执行异常\n",
encoding="utf-8",
)
runner = DoctorRunner()
checks._check_logs(runner)
finding = runner.report.find("logs.demo.recent_errors")
assert finding is not None
assert finding.status == DoctorFindingStatus.Degraded
assert finding.severity == DoctorSeverity.Warn
assert finding.affects_report_status is False
assert finding.context["component"] == "plugin"
assert runner.report.status.value == "healthy"
assert "[WARN/ADVISORY]" in format_text_report(runner.report)
def test_doctor_plugin_load_error_in_main_log_does_not_degrade_report(
tmp_path,
monkeypatch,
):
"""主日志中的插件加载异常应归入插件告警,不降低系统整体状态。"""
monkeypatch.setattr(settings, "CONFIG_DIR", str(tmp_path))
app_log = settings.LOG_PATH / "moviepilot.log"
app_log.parent.mkdir(parents=True, exist_ok=True)
app_log.write_text(
"【ERROR】2026-07-20 08:00:00 - plugin.py - 加载插件 Demo 出错:boom - Traceback (most recent call last):\n"
"Exception: boom\n",
encoding="utf-8",
)
runner = DoctorRunner()
checks._check_logs(runner)
finding = runner.report.find("logs.moviepilot.recent_errors")
assert finding is not None
assert finding.affects_report_status is False
assert finding.context["component"] == "plugin"
assert "Exception: boom" in finding.detail
assert runner.report.status.value == "healthy"
def test_doctor_plugin_error_mirrored_to_stdio_does_not_degrade_report(
tmp_path,
monkeypatch,
):
"""插件错误镜像到后端 stdio 日志时仍不应降低系统整体状态。"""
monkeypatch.setattr(settings, "CONFIG_DIR", str(tmp_path))
plugin_log = settings.LOG_PATH / "plugins" / "DemoPlugin.log"
plugin_log.parent.mkdir(parents=True, exist_ok=True)
plugin_log.write_text(
"【INFO】2026-07-20 08:00:00 - demo.py - 插件已启动\n",
encoding="utf-8",
)
stdio_log = settings.LOG_PATH / "moviepilot.stdout.log"
stdio_log.write_text(
"ERROR: [demoplugin] 2026-07-20 08:01:00 demo.py - task exception\n",
encoding="utf-8",
)
runner = DoctorRunner()
checks._check_logs(runner)
finding = runner.report.find("logs.moviepilot.stdout.recent_errors")
assert finding is not None
assert finding.affects_report_status is False
assert finding.context["component"] == "plugin"
assert runner.report.status.value == "healthy"
def test_doctor_core_log_error_still_degrades_report(tmp_path, monkeypatch):
"""核心日志错误仍应参与系统整体状态聚合。"""
monkeypatch.setattr(settings, "CONFIG_DIR", str(tmp_path))
app_log = settings.LOG_PATH / "moviepilot.log"
app_log.parent.mkdir(parents=True, exist_ok=True)
app_log.write_text(
"【ERROR】2026-07-20 08:00:00 - rss.py - 解析 RSS 失败 - Traceback (most recent call last):\n"
"RuntimeError: boom\n",
encoding="utf-8",
)
runner = DoctorRunner()
checks._check_logs(runner)
finding = runner.report.find("logs.moviepilot.recent_errors")
assert finding is not None
assert finding.affects_report_status is True
assert finding.context["component"] == "core"
assert runner.report.status.value == "degraded"
def test_doctor_mixed_plugin_and_core_log_errors_keep_core_status(
tmp_path,
monkeypatch,
):
"""同一主日志混有插件和核心错误时,仅核心错误应影响整体状态。"""
monkeypatch.setattr(settings, "CONFIG_DIR", str(tmp_path))
app_log = settings.LOG_PATH / "moviepilot.log"
app_log.parent.mkdir(parents=True, exist_ok=True)
app_log.write_text(
"【ERROR】2026-07-20 08:00:00 - plugin.py - 加载插件 Demo 出错:boom - Traceback (most recent call last):\n"
"Exception: plugin boom\n"
"【ERROR】2026-07-20 08:01:00 - rss.py - 解析 RSS 失败 - Traceback (most recent call last):\n"
"Exception: core boom\n",
encoding="utf-8",
)
runner = DoctorRunner()
checks._check_logs(runner)
core_finding = runner.report.find("logs.moviepilot.recent_errors")
plugin_finding = runner.report.find("logs.moviepilot.plugin_errors")
assert core_finding is not None
assert plugin_finding is not None
assert core_finding.affects_report_status is True
assert plugin_finding.affects_report_status is False
assert "core boom" in core_finding.detail
assert "plugin boom" in plugin_finding.detail
assert runner.report.status.value == "degraded"