diff --git a/services/ai_call_logger.py b/services/ai_call_logger.py index 9def60a..805475e 100644 --- a/services/ai_call_logger.py +++ b/services/ai_call_logger.py @@ -138,7 +138,11 @@ class _CallState: from services.llm_caller_registry import assert_known_caller assert_known_caller(caller, strict=False) except ImportError: - pass # registry 不可用時不阻擋(向下相容) + logger.warning( + "[AICallLogger] caller registry import failed; skipping caller validation (caller=%s)", + caller, + exc_info=True, + ) self.caller = caller self.provider = provider diff --git a/tests/test_ai_call_logger.py b/tests/test_ai_call_logger.py index 193e8d7..595cd13 100644 --- a/tests/test_ai_call_logger.py +++ b/tests/test_ai_call_logger.py @@ -18,6 +18,8 @@ ai_call_logger 單元測試 (Operation Ollama-First v5.0 — Phase 1) import os import sys import time +import builtins +import logging import pytest @@ -120,6 +122,24 @@ def test_context_manager_exception_path(reset_state): assert 'boom' in rec['error'] +def test_context_manager_logs_registry_import_failure(monkeypatch, caplog): + """caller registry 匯入失敗時不阻擋 LLM 遙測,但要留下診斷 log。""" + real_import = builtins.__import__ + + def _import_with_missing_registry(name, globals=None, locals=None, fromlist=(), level=0): + if name == "services.llm_caller_registry": + raise ImportError("registry unavailable") + return real_import(name, globals, locals, fromlist, level) + + monkeypatch.setattr(builtins, "__import__", _import_with_missing_registry) + caplog.set_level(logging.WARNING, logger="services.ai_call_logger") + + with log_ai_call('hermes_analyst', 'gcp_ollama', 'hermes3:latest') as ctx: + ctx.set_tokens(input=10, output=5) + + assert "caller registry import failed" in caplog.text + + def test_context_manager_explicit_fallback(reset_state): captured = reset_state with log_ai_call('openclaw_qa', 'gemini', 'gemini-2.5-flash') as ctx: