This commit is contained in:
@@ -2321,6 +2321,14 @@ def ppt_audit_history():
|
||||
def host_health_dashboard():
|
||||
"""三主機 Ollama + 4 個 MCP server 即時健康(同時寫入 host_health_probes 留歷史)"""
|
||||
import time as _time
|
||||
|
||||
def _session_uses_sqlite(session) -> bool:
|
||||
try:
|
||||
bind = session.get_bind()
|
||||
return getattr(getattr(bind, 'dialect', None), 'name', None) == 'sqlite'
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
ollama_hosts = []
|
||||
probe_records = [] # 收集本次 probe 結果以批次寫 DB
|
||||
try:
|
||||
@@ -2365,19 +2373,22 @@ def host_health_dashboard():
|
||||
try:
|
||||
_session = get_session()
|
||||
try:
|
||||
for rec in probe_records:
|
||||
_session.execute(
|
||||
sa_text("""
|
||||
INSERT INTO host_health_probes
|
||||
(host_label, host_url, healthy, unhealthy_mark,
|
||||
models_count, response_ms, error_msg)
|
||||
VALUES
|
||||
(:host_label, :host_url, :healthy, :unhealthy_mark,
|
||||
:models_count, :response_ms, :error_msg)
|
||||
"""),
|
||||
rec,
|
||||
)
|
||||
_session.commit()
|
||||
if _session_uses_sqlite(_session):
|
||||
logger.debug("Skipping host health probe persistence on SQLite")
|
||||
else:
|
||||
for rec in probe_records:
|
||||
_session.execute(
|
||||
sa_text("""
|
||||
INSERT INTO host_health_probes
|
||||
(host_label, host_url, healthy, unhealthy_mark,
|
||||
models_count, response_ms, error_msg)
|
||||
VALUES
|
||||
(:host_label, :host_url, :healthy, :unhealthy_mark,
|
||||
:models_count, :response_ms, :error_msg)
|
||||
"""),
|
||||
rec,
|
||||
)
|
||||
_session.commit()
|
||||
finally:
|
||||
_session.close()
|
||||
except Exception:
|
||||
|
||||
@@ -194,6 +194,42 @@ def test_host_health_200(client, monkeypatch):
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_host_health_skips_probe_persistence_on_sqlite(client, monkeypatch):
|
||||
"""Local visual QA uses SQLite; GET page should not warn on BIGINT autoincrement drift."""
|
||||
from routes import admin_observability_routes as mod
|
||||
import services.ollama_service as ollama_mod
|
||||
import requests as _r
|
||||
|
||||
class _Dialect:
|
||||
name = 'sqlite'
|
||||
|
||||
class _Bind:
|
||||
dialect = _Dialect()
|
||||
|
||||
session = _fake_session([])
|
||||
session.get_bind.return_value = _Bind()
|
||||
monkeypatch.setattr(mod, 'get_session', lambda: session)
|
||||
monkeypatch.setattr(ollama_mod, '_is_unhealthy', lambda _h: False, raising=False)
|
||||
monkeypatch.setattr(ollama_mod, '_unhealthy_marks', {}, raising=False)
|
||||
|
||||
class FakeResponse:
|
||||
status_code = 200
|
||||
|
||||
def json(self):
|
||||
return {'models': [{'name': 'bge-m3'}]}
|
||||
|
||||
monkeypatch.setattr(_r, 'get', lambda *_a, **_kw: FakeResponse())
|
||||
|
||||
r = client.get('/observability/host_health')
|
||||
|
||||
assert r.status_code == 200
|
||||
insert_calls = [
|
||||
call for call in session.execute.call_args_list
|
||||
if 'INSERT INTO host_health_probes' in str(call.args[0])
|
||||
]
|
||||
assert insert_calls == []
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────
|
||||
# Phase 33 Auth Hardening — 未登入必 302 redirect 到 /login
|
||||
# ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user