From fcfbe04a58a22809524eead960f77e271428d03d630e3b1a0923db812cf1b852 Mon Sep 17 00:00:00 2001 From: larssand Date: Wed, 1 Jul 2026 00:17:54 +0200 Subject: [PATCH] fix refresh of mcp con --- src/fgai/monitor.py | 26 ++++++++++++++++++++++++++ tests/test_monitor.py | 27 ++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/fgai/monitor.py b/src/fgai/monitor.py index b727e47..a2034e3 100644 --- a/src/fgai/monitor.py +++ b/src/fgai/monitor.py @@ -436,6 +436,30 @@ def write_status(status: dict[str, object], output: str) -> None: tmp_path.replace(output_path) +def write_refreshing_status(output: str) -> None: + output_path = Path(output) + try: + current = json.loads(output_path.read_text(encoding="utf-8")) if output_path.exists() else {} + except (json.JSONDecodeError, OSError): + current = {} + if not isinstance(current, dict): + current = {} + previous_mcp = current.get("capabilities", {}).get("graylog_mcp", {}) if isinstance(current.get("capabilities"), dict) else {} + current.setdefault("status_schema", 2) + current["generated_at"] = int(time.time()) + current["stale"] = False + current["stale_reason"] = "" + capabilities = current.setdefault("capabilities", {}) + if isinstance(capabilities, dict): + capabilities["graylog_mcp"] = { + "status": "refreshing", + "previous_status": previous_mcp.get("status", "") if isinstance(previous_mcp, dict) else "", + "previous_error": previous_mcp.get("error", "") if isinstance(previous_mcp, dict) else "", + } + current["status_cache"] = {"served_from_cache": False, "reason": "refreshing"} + write_status(current, output) + + def monitor_loop( log_path: str, output: str, @@ -460,6 +484,8 @@ def monitor_loop( runtime = ConfigStore(config_path).read() if config_path and Path(config_path).exists() else {} effective_llm = bool(runtime.get("llm_enabled")) if runtime else llm effective_model = str(runtime.get("llm_model") or llm_model or "") + if runtime.get("log_source") == "graylog_mcp": + write_refreshing_status(output) status = build_status( log_path, policy_path=policy_path, anomaly_limit=anomaly_limit, baseline_path=baseline_path, config_path=config_path, history_path=history_path, diff --git a/tests/test_monitor.py b/tests/test_monitor.py index 7cb9a97..28f6452 100644 --- a/tests/test_monitor.py +++ b/tests/test_monitor.py @@ -5,7 +5,7 @@ from pathlib import Path from unittest.mock import patch from fgai.history import StatusSnapshotStore -from fgai.monitor import add_llm_assessment, build_status, cached_status_with_error, write_status +from fgai.monitor import add_llm_assessment, build_status, cached_status_with_error, write_refreshing_status, write_status class MonitorTests(unittest.TestCase): @@ -39,6 +39,31 @@ class MonitorTests(unittest.TestCase): self.assertTrue(output.exists()) + def test_write_refreshing_status_clears_stale_mcp_error(self): + with tempfile.TemporaryDirectory() as tmp: + output = Path(tmp) / "status.json" + output.write_text( + json.dumps( + { + "status_schema": 2, + "stale": True, + "stale_reason": "live_mcp_error", + "capabilities": {"graylog_mcp": {"status": "error", "error": "old dns error"}}, + } + ), + encoding="utf-8", + ) + + write_refreshing_status(str(output)) + + status = json.loads(output.read_text(encoding="utf-8")) + self.assertFalse(status["stale"]) + self.assertEqual(status["stale_reason"], "") + self.assertEqual(status["capabilities"]["graylog_mcp"]["status"], "refreshing") + self.assertEqual(status["capabilities"]["graylog_mcp"]["previous_status"], "error") + self.assertEqual(status["capabilities"]["graylog_mcp"]["previous_error"], "old dns error") + self.assertFalse(status["status_cache"]["served_from_cache"]) + def test_profile_readiness_includes_stream_and_profile_names(self): with tempfile.TemporaryDirectory() as tmp: config_path = Path(tmp) / "config.json"