From 61dfce06bfd29f0c5b0a718573b5b268ab5e6f3e Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Mon, 26 Jan 2026 21:19:51 -0800 Subject: [PATCH] Optimize process_dynamic_callbacks with early return and per-callback conditionals - Add early return when all callbacks are None (common case) - Add per-callback conditionals to only process callbacks that are set - Reorder processing: success before async_success, failure before async_failure (required because success/failure processing adds items to async lists) Profiling shows ~79% reduction in process_dynamic_callbacks time (11.5% -> 0.8%) --- litellm/litellm_core_utils/litellm_logging.py | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index bdbbc7579b7..ec06cf8f7db 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -412,30 +412,45 @@ class Logging(LiteLLMLoggingBaseClass): If a callback is in litellm._known_custom_logger_compatible_callbacks, it needs to be intialized and added to the respective dynamic_* callback list. """ - # Process input callbacks - self.dynamic_input_callbacks = self._process_dynamic_callback_list( - self.dynamic_input_callbacks, dynamic_callbacks_type="input" - ) + # Early exit if all callbacks are None (common case) + if ( + self.dynamic_input_callbacks is None + and self.dynamic_success_callbacks is None + and self.dynamic_async_success_callbacks is None + and self.dynamic_failure_callbacks is None + and self.dynamic_async_failure_callbacks is None + ): + return - # Process failure callbacks - self.dynamic_failure_callbacks = self._process_dynamic_callback_list( - self.dynamic_failure_callbacks, dynamic_callbacks_type="failure" - ) + # Process input callbacks (standalone - no dependencies) + if self.dynamic_input_callbacks is not None: + self.dynamic_input_callbacks = self._process_dynamic_callback_list( + self.dynamic_input_callbacks, dynamic_callbacks_type="input" + ) - # Process async failure callbacks - self.dynamic_async_failure_callbacks = self._process_dynamic_callback_list( - self.dynamic_async_failure_callbacks, dynamic_callbacks_type="async_failure" - ) + # Process success BEFORE async_success (success processing adds to async_success) + if self.dynamic_success_callbacks is not None: + self.dynamic_success_callbacks = self._process_dynamic_callback_list( + self.dynamic_success_callbacks, dynamic_callbacks_type="success" + ) - # Process success callbacks - self.dynamic_success_callbacks = self._process_dynamic_callback_list( - self.dynamic_success_callbacks, dynamic_callbacks_type="success" - ) + # Process async_success AFTER success + if self.dynamic_async_success_callbacks is not None: + self.dynamic_async_success_callbacks = self._process_dynamic_callback_list( + self.dynamic_async_success_callbacks, dynamic_callbacks_type="async_success" + ) - # Process async success callbacks - self.dynamic_async_success_callbacks = self._process_dynamic_callback_list( - self.dynamic_async_success_callbacks, dynamic_callbacks_type="async_success" - ) + # Process failure BEFORE async_failure (failure processing adds to async_failure) + if self.dynamic_failure_callbacks is not None: + self.dynamic_failure_callbacks = self._process_dynamic_callback_list( + self.dynamic_failure_callbacks, dynamic_callbacks_type="failure" + ) + + # Process async_failure AFTER failure + if self.dynamic_async_failure_callbacks is not None: + self.dynamic_async_failure_callbacks = self._process_dynamic_callback_list( + self.dynamic_async_failure_callbacks, dynamic_callbacks_type="async_failure" + ) def _process_dynamic_callback_list( self,