From f1136fd217f19a0fed43468e4cffce3e6041ea74 Mon Sep 17 00:00:00 2001 From: Dat Daryl Ngo <97070834+arizedatngo@users.noreply.github.com> Date: Tue, 13 May 2025 18:45:39 +0200 Subject: [PATCH] fix: URL encode OTEL_EXPORTER_OTLP_TRACES_HEADERS for Phoenix Integration (#10654) * fix: URL encode OTEL_EXPORTER_OTLP_TRACES_HEADERS for Arize Phoenix integration - Add URL encoding for Bearer token in authorization header - Follow OpenTelemetry Protocol Exporter specification - Fix header format validation error in Phoenix integration * add mock test for arize phoenix --- litellm/integrations/arize/arize_phoenix.py | 3 +- .../integrations/arize/test_arize_phoenix.py | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/litellm/integrations/arize/test_arize_phoenix.py diff --git a/litellm/integrations/arize/arize_phoenix.py b/litellm/integrations/arize/arize_phoenix.py index 2b4909885a..044486fcd2 100644 --- a/litellm/integrations/arize/arize_phoenix.py +++ b/litellm/integrations/arize/arize_phoenix.py @@ -1,4 +1,5 @@ import os +import urllib.parse from typing import TYPE_CHECKING, Any, Union from litellm._logging import verbose_logger @@ -69,7 +70,7 @@ class ArizePhoenixLogger: otlp_auth_headers = f"api_key={api_key}" elif api_key is not None: # api_key/auth is optional for self hosted phoenix - otlp_auth_headers = f"Authorization=Bearer {api_key}" + otlp_auth_headers = f"Authorization={urllib.parse.quote(f'Bearer {api_key}')}" return ArizePhoenixConfig( otlp_auth_headers=otlp_auth_headers, protocol=protocol, endpoint=endpoint diff --git a/tests/litellm/integrations/arize/test_arize_phoenix.py b/tests/litellm/integrations/arize/test_arize_phoenix.py new file mode 100644 index 0000000000..a7acab986e --- /dev/null +++ b/tests/litellm/integrations/arize/test_arize_phoenix.py @@ -0,0 +1,34 @@ +import unittest +from unittest.mock import patch +from litellm.integrations.arize.arize_phoenix import ArizePhoenixLogger + +class TestArizePhoenixConfig(unittest.TestCase): + + @patch.dict('os.environ', { + 'PHOENIX_API_KEY': 'test_api_key', + 'PHOENIX_COLLECTOR_HTTP_ENDPOINT': 'http://test.endpoint' + }) + def test_get_arize_phoenix_config_http(self): + # Call the function to get the configuration + config = ArizePhoenixLogger.get_arize_phoenix_config() + + # Verify the configuration + self.assertEqual(config.otlp_auth_headers, 'Authorization=Bearer%20test_api_key') + self.assertEqual(config.endpoint, 'http://test.endpoint') + self.assertEqual(config.protocol, 'otlp_http') + + @patch.dict('os.environ', { + 'PHOENIX_API_KEY': 'test_api_key', + 'PHOENIX_COLLECTOR_ENDPOINT': 'grpc://test.endpoint' + }) + def test_get_arize_phoenix_config_grpc(self): + # Call the function to get the configuration + config = ArizePhoenixLogger.get_arize_phoenix_config() + + # Verify the configuration + self.assertEqual(config.otlp_auth_headers, 'Authorization=Bearer%20test_api_key') + self.assertEqual(config.endpoint, 'grpc://test.endpoint') + self.assertEqual(config.protocol, 'otlp_grpc') + +if __name__ == '__main__': + unittest.main() \ No newline at end of file