Add live AI checks to system health (#3155)

* Add live AI checks to system health

Give super admins a dedicated AI status view with bounded liveness probes for LLMs, vector stores, pgvector, and embedding endpoints. Record sanitized failures in both the system debug log and Rails logger, and document the recommended local configuration.\n\nCloses #3145

* Fix AI health CI checks

* Address AI health review feedback

* Correct Ollama model preload guidance

* Distinguish OpenAI-compatible providers

* Make Ollama startup readiness explicit

* Recognize Cloudflare AI endpoints
This commit is contained in:
Juan José Mata
2026-08-24 22:41:08 +02:00
committed by GitHub
parent c26b16d36f
commit fd6f4ff078
24 changed files with 1773 additions and 120 deletions
+54
View File
@@ -0,0 +1,54 @@
require "application_system_test_case"
class Admin::SystemHealthTest < ApplicationSystemTestCase
setup do
sign_in users(:sure_support_staff)
Setting.stubs(:llm_provider).returns("openai")
Setting.stubs(:openai_access_token).returns(nil)
Setting.stubs(:openai_uri_base).returns(nil)
Setting.stubs(:openai_model).returns(nil)
stub_healthy_sidekiq
AiHealth::Probe.any_instance.stubs(:llm).returns(probe_result(:passing))
AiHealth::Probe.any_instance.stubs(:openai_vector_store).returns(probe_result(:passing))
end
test "selecting AI status runs live probes" do
ClimateControl.modify(
"OPENAI_ACCESS_TOKEN" => "test-token",
"OPENAI_URI_BASE" => nil,
"OPENAI_MODEL" => nil,
"VECTOR_STORE_PROVIDER" => nil
) do
visit admin_system_health_path
click_button "AI status"
assert_current_path admin_system_health_path(tab: "ai")
assert_selector "button[role='tab'][aria-selected='true']", text: "AI status"
assert_text "Live check passed"
assert_text "Live checks passed"
end
end
private
def probe_result(status)
AiHealth::Probe::Result.new(
status: status,
checked_at: Time.current,
failure_code: nil,
http_status: nil
)
end
def stub_healthy_sidekiq
SidekiqHealth.any_instance.stubs(:healthy?).returns(true)
SidekiqHealth.any_instance.stubs(:processes_count).returns(1)
SidekiqHealth.any_instance.stubs(:last_heartbeat_at).returns(Time.current)
SidekiqHealth.any_instance.stubs(:max_queue_latency).returns(0.0)
SidekiqHealth.any_instance.stubs(:enqueued_count).returns(0)
SidekiqHealth.any_instance.stubs(:retry_count).returns(0)
SidekiqHealth.any_instance.stubs(:failed_count).returns(0)
SidekiqHealth.any_instance.stubs(:processed_count).returns(42)
SidekiqHealth.any_instance.stubs(:queue_breakdown).returns([ [ "default", 0, 0.0 ] ])
end
end