fix(proxy): fall back to string callback when custom-logger init fails

The custom-logger class may not initialize without env credentials; keep
the string in litellm.success_callback in that case so standard-route
logging still works. Test sets LANGFUSE env so it exercises the instance
registration path.
This commit is contained in:
wadrzl55333 2026-08-28 16:57:50 +08:00
parent 84afc7e924
commit ed99488fd3
2 changed files with 24 additions and 8 deletions

View file

@ -709,8 +709,25 @@ def _register_config_custom_logger_callback(callback: str, logging_event: Litera
"""Register a config-file custom-logger name as an instance, not a string.
Pass-through endpoints log through the async success path only; a string in
``litellm.success_callback`` never reaches them. Mirrors the DB-config path.
``litellm.success_callback`` never reaches them. Falls back to the string
when the custom-logger class cannot be initialized (e.g. missing env
credentials), so standard-route logging still works. Mirrors the DB-config path.
"""
from litellm.litellm_core_utils.litellm_logging import (
_init_custom_logger_compatible_class,
)
if (
_init_custom_logger_compatible_class( # pyright: ignore[reportPrivateUsage] # mirrors DB-config path
callback, internal_usage_cache=None, llm_router=None
)
is None
):
if logging_event == "success":
litellm.logging_callback_manager.add_litellm_success_callback(callback)
else:
litellm.logging_callback_manager.add_litellm_failure_callback(callback)
return
_add_custom_logger_callback_to_specific_event( # pyright: ignore[reportPrivateUsage] # mirrors DB-config path
callback, logging_event
)
@ -5134,11 +5151,6 @@ class ProxyConfig:
# these are litellm callbacks - "langfuse", "sentry", "wandb"
else:
if callback in litellm._known_custom_logger_compatible_callbacks:
# drop the string first: _add_custom_logger_callback_to_specific_event
# skips registration (and the string removal inside it) when an
# instance already exists from an earlier registration
if callback in litellm.success_callback:
litellm.success_callback.remove(callback)
_register_config_custom_logger_callback(callback, "success")
else:
litellm.logging_callback_manager.add_litellm_success_callback(callback)
@ -5169,8 +5181,6 @@ class ProxyConfig:
# these are litellm callbacks - "langfuse", "sentry", "wandb"
else:
if callback in litellm._known_custom_logger_compatible_callbacks:
if callback in litellm.failure_callback:
litellm.failure_callback.remove(callback)
_register_config_custom_logger_callback(callback, "failure")
else:
litellm.logging_callback_manager.add_litellm_failure_callback(callback)

View file

@ -180,6 +180,12 @@ async def test_config_file_success_callback_registers_custom_logger_instance(mon
monkeypatch.setattr(litellm, "_async_success_callback", [])
monkeypatch.setattr(litellm, "failure_callback", [])
monkeypatch.setattr(litellm, "_async_failure_callback", [])
# the custom-logger instance path needs env credentials; without them the
# config path falls back to the string and this test would not exercise
# the instance registration
monkeypatch.setenv("LANGFUSE_PUBLIC_KEY", "pk-lf-test")
monkeypatch.setenv("LANGFUSE_SECRET_KEY", "sk-lf-test")
monkeypatch.setenv("LANGFUSE_HOST", "http://localhost:3000")
config_content = {
"litellm_settings": {