diff --git a/litellm/integrations/arize/arize.py b/litellm/integrations/arize/arize.py index 23822801b41..1d78e4cc69c 100644 --- a/litellm/integrations/arize/arize.py +++ b/litellm/integrations/arize/arize.py @@ -8,11 +8,9 @@ import os from datetime import datetime from typing import TYPE_CHECKING, Any, Optional, Union -from litellm.integrations.additional_logging_utils import AdditionalLoggingUtils from litellm.integrations.arize import _utils from litellm.integrations.opentelemetry import OpenTelemetry from litellm.types.integrations.arize import ArizeConfig -from litellm.types.integrations.base_health_check import IntegrationHealthCheckStatus from litellm.types.services import ServiceLoggerPayload from litellm.types.utils import StandardCallbackDynamicParams @@ -28,7 +26,7 @@ else: Span = Any -class ArizeLogger(OpenTelemetry, AdditionalLoggingUtils): +class ArizeLogger(OpenTelemetry): def set_attributes(self, span: Span, kwargs, response_obj: Optional[Any]): ArizeLogger.set_arize_attributes(span, kwargs, response_obj) return @@ -143,87 +141,3 @@ class ArizeLogger(OpenTelemetry, AdditionalLoggingUtils): ) return dynamic_headers - - async def async_health_check(self, standard_callback_dynamic_params: Optional[StandardCallbackDynamicParams] = None) -> IntegrationHealthCheckStatus: - """ - Check if Arize service is healthy by testing OTEL trace export - - Args: - standard_callback_dynamic_params: Dynamic parameters containing arize_api_key and arize_space_key/arize_space_id - - Returns: - IntegrationHealthCheckStatus with status and optional error message - """ - try: - api_key = None - space_key = None - - if standard_callback_dynamic_params: - api_key = standard_callback_dynamic_params.get("arize_api_key") - space_key = ( - standard_callback_dynamic_params.get("arize_space_key") or - standard_callback_dynamic_params.get("arize_space_id") # fallback for backwards compatibility - ) - - if not api_key: - api_key = os.environ.get("ARIZE_API_KEY") - if not space_key: - space_key = os.environ.get("ARIZE_SPACE_KEY") - - if not api_key or not space_key: - return IntegrationHealthCheckStatus( - status="unhealthy", - error_message="Arize credentials not configured. Please set arize_api_key and arize_space_key parameters or ARIZE_API_KEY and ARIZE_SPACE_KEY environment variables." - ) - - # Get Arize configuration - arize_config = ArizeLogger.get_arize_config() - - # Validate configuration - if not arize_config.endpoint: - return IntegrationHealthCheckStatus( - status="unhealthy", - error_message="Arize endpoint not configured. Using default endpoint https://otlp.arize.com/v1" - ) - - try: - test_headers = { - "arize-space-id": space_key.strip(), - "api_key": api_key.strip(), - } - - endpoint = arize_config.endpoint or "https://otlp.arize.com/v1" - - # For a basic health check, we just validate that the configuration is properly formed - # A full test would require actually sending a trace, which might be overkill for health checks - - return IntegrationHealthCheckStatus( - status="healthy", - error_message=None - ) - - except Exception as config_error: - return IntegrationHealthCheckStatus( - status="unhealthy", - error_message=f"Arize configuration error: {str(config_error)}" - ) - - except Exception as e: - return IntegrationHealthCheckStatus( - status="unhealthy", - error_message=f"Arize health check failed: {str(e)}" - ) - - async def get_request_response_payload( - self, - request_id: str, - start_time_utc: Optional[datetime] = None, - end_time_utc: Optional[datetime] = None, - ) -> Optional[dict]: - """ - Get the request and response payload for a given request_id from Arize. - - Note: Arize is primarily for observability/tracing, not request/response storage. - This method returns None as Arize doesn't typically store raw payloads. - """ - return None diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 292e69b6a8c..c5370eb7d70 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -2368,17 +2368,6 @@ class AllCallbacks(LiteLLMPydanticObjectBase): ui_callback_name="Lago Billing", ) - arize: CallbackOnUI = CallbackOnUI( - litellm_callback_name="arize", - litellm_callback_params=[ - "ARIZE_API_KEY", - "ARIZE_SPACE_KEY", - "ARIZE_ENDPOINT", - "ARIZE_HTTP_ENDPOINT", - ], - ui_callback_name="Arize", - ) - class SpendLogsMetadata(TypedDict): """ diff --git a/litellm/proxy/health_endpoints/_health_endpoints.py b/litellm/proxy/health_endpoints/_health_endpoints.py index 8b06b46f76e..883bff3185f 100644 --- a/litellm/proxy/health_endpoints/_health_endpoints.py +++ b/litellm/proxy/health_endpoints/_health_endpoints.py @@ -75,7 +75,6 @@ async def health_services_endpoint( # noqa: PLR0915 "braintrust", "datadog", "generic_api", - "arize", ], str, ] = fastapi.Query(description="Specify the service being hit."), @@ -114,7 +113,6 @@ async def health_services_endpoint( # noqa: PLR0915 "langsmith", "datadog", "generic_api", - "arize", ]: raise HTTPException( status_code=400, @@ -167,19 +165,6 @@ async def health_services_endpoint( # noqa: PLR0915 "status": "success", "message": "Mock LLM request made - check langfuse.", } - elif service == "arize": - from litellm.integrations.arize.arize import ArizeLogger - - arize_logger = ArizeLogger() - response = await arize_logger.async_health_check() - return { - "status": response["status"], - "message": ( - response["error_message"] - if response["status"] == "unhealthy" - else "Arize is healthy and ready to receive traces" - ), - } if service == "webhook": user_info = CallInfo( diff --git a/ui/litellm-dashboard/src/components/callback_info_helpers.tsx b/ui/litellm-dashboard/src/components/callback_info_helpers.tsx index 595bde3fc5b..66ef4d87385 100644 --- a/ui/litellm-dashboard/src/components/callback_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/callback_info_helpers.tsx @@ -76,7 +76,7 @@ export const callbackInfo: Record = { supports_key_team_logging: true, dynamic_params: { "arize_api_key": "password", - "arize_space_key": "text", + "arize_space_id": "text", }, description: "Arize Logging Integration" }, diff --git a/ui/litellm-dashboard/src/components/settings.tsx b/ui/litellm-dashboard/src/components/settings.tsx index 2da70ff0aab..55997ce95cd 100644 --- a/ui/litellm-dashboard/src/components/settings.tsx +++ b/ui/litellm-dashboard/src/components/settings.tsx @@ -48,10 +48,8 @@ import { callback_map, callbackInfo, Callbacks, - reverse_callback_map, } from "./callback_info_helpers"; import { parseErrorMessage } from "./shared/errorUtils"; -import Image from "next/image"; interface SettingsPageProps { accessToken: string | null; userRole: string | null; @@ -109,8 +107,6 @@ const Settings: React.FC = ({ ); const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false); const [callbackToDelete, setCallbackToDelete] = useState(null); - const [testingConnection, setTestingConnection] = useState(false); - const [connectionStatus, setConnectionStatus] = useState<'success' | 'error' | null>(null); useEffect(() => { if (showEditCallback && selectedEditCallback) { @@ -255,133 +251,6 @@ const Settings: React.FC = ({ } }; - const handleCallbackSelectChange = (value: string) => { - // Reset connection status when callback changes - setConnectionStatus(null); - - // Find callback by internal value - check if allCallbacks is array first - let selectedCallbackObject = null; - if (Array.isArray(allCallbacks) && allCallbacks.length > 0) { - selectedCallbackObject = allCallbacks.find( - cb => cb.litellm_callback_name === value - ); - } - - if (selectedCallbackObject) { - handleSelectedCallbackChange(selectedCallbackObject); - } else { - // Fallback: use dynamic params from callbackInfo - const displayName = reverse_callback_map[value]; - if (displayName && callbackInfo[displayName]?.dynamic_params) { - const dynamicParams = Object.keys(callbackInfo[displayName].dynamic_params); - setSelectedCallback(value); - setSelectedCallbackParams(dynamicParams); - } else { - // Final fallback: try to find in allCallbacks by index (for backward compatibility) - let legacyCallback = null; - if (Array.isArray(allCallbacks)) { - // The old system used array indices, check if value is a number - const numericValue = parseInt(value); - if (!isNaN(numericValue) && allCallbacks[numericValue]) { - legacyCallback = allCallbacks[numericValue]; - } - } - - if (legacyCallback) { - handleSelectedCallbackChange(legacyCallback); - } else { - setSelectedCallback(value); - setSelectedCallbackParams([]); - } - } - } - }; - - const getFieldType = (paramName: string, callbackName: string): "text" | "password" => { - const displayName = reverse_callback_map[callbackName]; - if (displayName && callbackInfo[displayName]?.dynamic_params) { - const paramType = callbackInfo[displayName].dynamic_params[paramName]; - return paramType === "password" ? "password" : "text"; - } - // Default heuristics for legacy callbacks - return paramName.toLowerCase().includes("key") || - paramName.toLowerCase().includes("secret") || - paramName.toLowerCase().includes("token") ? "password" : "text"; - }; - - const getFieldLabel = (paramName: string): string => { - return paramName - .replace(/_/g, " ") - .replace(/\b\w/g, l => l.toUpperCase()); - }; - - const getFieldPlaceholder = (paramName: string, callbackName: string): string => { - const displayName = reverse_callback_map[callbackName]; - - if (displayName === "Arize") { - if (paramName === "ARIZE_API_KEY" || paramName === "arize_api_key") return "Enter your Arize API Key..."; - if (paramName === "ARIZE_SPACE_KEY" || paramName === "arize_space_id") return "Enter your Arize Space Key..."; - if (paramName === "ARIZE_ENDPOINT" || paramName === "ARIZE_HTTP_ENDPOINT") return "Optional: Custom endpoint URL"; - } - - return `Enter ${getFieldLabel(paramName)}...`; - }; - - const isRequiredField = (paramName: string, callbackName: string): boolean => { - const displayName = reverse_callback_map[callbackName]; - - if (displayName === "Arize") { - return (paramName === "ARIZE_API_KEY" || paramName === "arize_api_key") || - (paramName === "ARIZE_SPACE_KEY" || paramName === "arize_space_id"); - } - - // Default: all fields are required except endpoints - return !paramName.toLowerCase().includes("endpoint") && - !paramName.toLowerCase().includes("base") && - !paramName.toLowerCase().includes("host"); - }; - - const testCallbackConnection = async () => { - if (!selectedCallback || !accessToken) return; - - setTestingConnection(true); - setConnectionStatus(null); - - try { - const formValues = addForm.getFieldsValue(); - - // Build query params for connection test - const params = new URLSearchParams(); - selectedCallbackParams.forEach(param => { - const value = formValues[param]; - if (value) { - // Convert backend param names to dynamic param names - let dynamicParamName = param.toLowerCase(); - if (selectedCallback === "arize") { - if (param === "ARIZE_API_KEY" || param === "arize_api_key") dynamicParamName = "arize_api_key"; - if (param === "ARIZE_SPACE_KEY" || param === "arize_space_id") dynamicParamName = "arize_space_id"; - } - params.append(dynamicParamName, value); - } - }); - - const response = await serviceHealthCheck(accessToken, selectedCallback); - - if (response) { - setConnectionStatus('success'); - NotificationsManager.success('Connection test successful!'); - } else { - setConnectionStatus('error'); - NotificationsManager.error('Connection test failed'); - } - } catch (error) { - setConnectionStatus('error'); - NotificationsManager.fromBackend(error); - } finally { - setTestingConnection(false); - } - }; - const handleSaveAlerts = async () => { if (!accessToken) { return; @@ -777,7 +646,12 @@ const Settings: React.FC = ({ rules={[{ required: true, message: "Please select a callback" }]} > - )} - - ); - })} - - {selectedCallback && selectedCallbackParams.length > 0 && ( -
- {connectionStatus === 'success' && ( - - - Connection successful - - )} - {connectionStatus === 'error' && ( - - - Connection failed - - )} - { - const value = addForm.getFieldValue(param); - return isRequiredField(param, selectedCallback || "") ? value : true; - })} + selectedCallbackParams.map((param) => ( + - {testingConnection ? 'Testing...' : 'Test Connection'} - -
- )} + + + ))}
Save