From ac2d55d272aa7690236fefccce6b6f400cc0ba3d Mon Sep 17 00:00:00 2001 From: Milan Date: Tue, 28 Apr 2026 14:35:07 +0300 Subject: [PATCH] fix(proxy): surface callback env vars in config API Made-with: Cursor --- litellm/proxy/common_utils/callback_utils.py | 3 +- .../proxy/common_utils/test_callback_utils.py | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/common_utils/callback_utils.py b/litellm/proxy/common_utils/callback_utils.py index 7ddd722a80e..25fbc0d4461 100644 --- a/litellm/proxy/common_utils/callback_utils.py +++ b/litellm/proxy/common_utils/callback_utils.py @@ -1,3 +1,4 @@ +import os from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Literal, Optional import litellm @@ -528,7 +529,7 @@ def process_callback( for _var in env_vars: env_variable = environment_variables.get(_var, None) if env_variable is None: - env_vars_dict[_var] = None + env_vars_dict[_var] = os.getenv(_var) else: env_vars_dict[_var] = env_variable diff --git a/tests/test_litellm/proxy/common_utils/test_callback_utils.py b/tests/test_litellm/proxy/common_utils/test_callback_utils.py index c6132194c74..a856a19dcad 100644 --- a/tests/test_litellm/proxy/common_utils/test_callback_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_callback_utils.py @@ -76,6 +76,91 @@ def test_process_callback_with_no_required_env_vars(mock_get_env_vars): assert result["variables"] == {} +@patch( + "litellm.proxy.common_utils.callback_utils.CustomLogger.get_callback_env_vars", + return_value=["GENERIC_LOGGER_ENDPOINT", "GENERIC_LOGGER_HEADERS"], +) +def test_process_callback_generic_api_falls_back_to_os_env( + mock_get_env_vars, monkeypatch +): + monkeypatch.setenv("GENERIC_LOGGER_ENDPOINT", "https://callback.example.com") + monkeypatch.setenv("GENERIC_LOGGER_HEADERS", "Authorization=Bearer token") + + result = process_callback( + _callback="generic_api", + callback_type="success", + environment_variables={}, + ) + + assert result["variables"] == { + "GENERIC_LOGGER_ENDPOINT": "https://callback.example.com", + "GENERIC_LOGGER_HEADERS": "Authorization=Bearer token", + } + + +@patch( + "litellm.proxy.common_utils.callback_utils.CustomLogger.get_callback_env_vars", + return_value=["GENERIC_LOGGER_ENDPOINT", "GENERIC_LOGGER_HEADERS"], +) +def test_process_callback_custom_callback_api_falls_back_to_os_env( + mock_get_env_vars, monkeypatch +): + monkeypatch.setenv("GENERIC_LOGGER_ENDPOINT", "https://callback.example.com") + monkeypatch.setenv("GENERIC_LOGGER_HEADERS", "Authorization=Bearer token") + + result = process_callback( + _callback="custom_callback_api", + callback_type="success", + environment_variables={}, + ) + + assert result["variables"] == { + "GENERIC_LOGGER_ENDPOINT": "https://callback.example.com", + "GENERIC_LOGGER_HEADERS": "Authorization=Bearer token", + } + + +@patch( + "litellm.proxy.common_utils.callback_utils.CustomLogger.get_callback_env_vars", + return_value=["GENERIC_LOGGER_ENDPOINT", "GENERIC_LOGGER_HEADERS"], +) +def test_process_callback_config_value_wins_over_os_env(mock_get_env_vars, monkeypatch): + monkeypatch.setenv("GENERIC_LOGGER_ENDPOINT", "https://env.example.com") + monkeypatch.setenv("GENERIC_LOGGER_HEADERS", "Authorization=Bearer env") + + result = process_callback( + _callback="generic_api", + callback_type="success", + environment_variables={ + "GENERIC_LOGGER_ENDPOINT": "https://config.example.com", + "GENERIC_LOGGER_HEADERS": "Authorization=Bearer config", + }, + ) + + assert result["variables"] == { + "GENERIC_LOGGER_ENDPOINT": "https://config.example.com", + "GENERIC_LOGGER_HEADERS": "Authorization=Bearer config", + } + + +@patch( + "litellm.proxy.common_utils.callback_utils.CustomLogger.get_callback_env_vars", + return_value=["LANGFUSE_PUBLIC_KEY"], +) +def test_process_callback_falls_back_to_os_env_for_registered_callback_vars( + mock_get_env_vars, monkeypatch +): + monkeypatch.setenv("LANGFUSE_PUBLIC_KEY", "pk-env") + + result = process_callback( + _callback="langfuse", + callback_type="success", + environment_variables={}, + ) + + assert result["variables"] == {"LANGFUSE_PUBLIC_KEY": "pk-env"} + + def test_normalize_callback_names_none_returns_empty_list(): assert normalize_callback_names(None) == [] assert normalize_callback_names([]) == []