fix(otel): keep bogus exclusion env fatal when a preset parses it

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yucheng 2026-09-26 15:46:37 +00:00
parent f71cee9e32
commit fdf26d8848
3 changed files with 32 additions and 8 deletions

View file

@ -377,7 +377,8 @@ def validate_otel_v2_excluded_services_env(settings: object) -> None:
init errors, so a bogus value would otherwise degrade to the legacy callback
silently. Splitting and normalizing here raises the same ``ValueError`` the
field raises. An explicit ``callback_settings.otel.excluded_services`` wins
over the env var, so a bad env value is inert then and must not block boot.
over the env var, so the caller skips this check only when no V2 preset
callback that would still parse the env is configured.
"""
if not is_otel_v2_enabled():
return

View file

@ -180,8 +180,14 @@ def initialize_callbacks_on_proxy(
validate_otel_v2_callback_settings(callback_specific_params.get("otel"))
from litellm.integrations.otel.model.config import validate_otel_v2_excluded_services_env
from litellm.integrations.otel.presets import PRESET_BY_CALLBACK
validate_otel_v2_excluded_services_env(callback_specific_params.get("otel") if "otel" in value else None)
preset_present: Final = any(
isinstance(entry, str) and entry != "otel" and entry in PRESET_BY_CALLBACK for entry in value
)
validate_otel_v2_excluded_services_env(
callback_specific_params.get("otel") if "otel" in value and not preset_present else None
)
# check if callback is a custom logger compatible callback
if isinstance(callback, str):

View file

@ -296,12 +296,7 @@ def test_valid_config_excluded_services_tolerates_bogus_env(
langfuse_vars: dict[str, JsonValue],
tmp_path: Path,
) -> None:
def with_langfuse_otel(config: dict) -> None:
config["litellm_settings"]["callbacks"] = ["otel", "langfuse_otel"]
config: Final = _config_with(
tmp_path, otel_audit_config, otel={"excluded_services": ["postgres"]}, extra=with_langfuse_otel
)
config: Final = _config_with(tmp_path, otel_audit_config, otel={"excluded_services": ["postgres"]})
with owned_proxy(
gateway, tmp_path, {"LITELLM_OTEL_V2": "1", "LITELLM_OTEL_EXCLUDED_SERVICES": "auth"}, config=config, workers=2
) as candidate:
@ -318,6 +313,28 @@ def test_valid_config_excluded_services_tolerates_bogus_env(
)
def test_bogus_excluded_services_env_fails_proxy_start_with_preset_alongside_otel(
gateway: Gateway, otel_audit_config: AuditConfigWriter, tmp_path: Path
) -> None:
def with_langfuse_otel(config: dict) -> None:
config["litellm_settings"]["callbacks"] = ["otel", "langfuse_otel"]
config: Final = _config_with(
tmp_path, otel_audit_config, otel={"excluded_services": ["postgres"]}, extra=with_langfuse_otel
)
log_dir: Final = Path(os.environ.get("INTEGRATION_RESULTS_DIR", str(tmp_path)))
before: Final = frozenset(log_dir.glob("owned-proxy-*.log"))
with pytest.raises(AssertionError, match="readiness"):
with owned_proxy_process(
gateway, tmp_path, {"LITELLM_OTEL_V2": "1", "LITELLM_OTEL_EXCLUDED_SERVICES": "auth"}, config=config, workers=2
):
pass
logs: Final = [path.read_text() for path in frozenset(log_dir.glob("owned-proxy-*.log")) - before]
assert logs, "no owned proxy log written"
text: Final = "\n".join(logs)
assert "'auth' is not a datastore service" in text, text[-3000:]
def test_bogus_excluded_services_env_fails_proxy_start_without_otel_callback(
gateway: Gateway, otel_audit_config: AuditConfigWriter, tmp_path: Path
) -> None: