From bdae5c63b1dbd8960c028d23bb0012204e5e38ec Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 1 Apr 2026 08:41:20 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20address=20PR=20review=20comments=20?= =?UTF-8?q?=E2=80=94=20tracing=20override,=20executor=20init=20order,=20st?= =?UTF-8?q?din=20guard,=20unused=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.5 --- lib/crewai/src/crewai/events/event_bus.py | 14 +++++++++----- .../events/listeners/tracing/trace_listener.py | 5 +++-- .../src/crewai/events/listeners/tracing/utils.py | 11 ++++++++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/crewai/src/crewai/events/event_bus.py b/lib/crewai/src/crewai/events/event_bus.py index 6b906309d..eefe1ad88 100644 --- a/lib/crewai/src/crewai/events/event_bus.py +++ b/lib/crewai/src/crewai/events/event_bus.py @@ -417,11 +417,6 @@ class CrewAIEventsBus: ... await asyncio.wrap_future(future) # In async test ... # or future.result(timeout=5.0) in sync code """ - # Lazily initialize executor and event loop on first emit - self._ensure_executor_initialized() - # Track that we have pending events for flush optimization - self._has_pending_events = True - event.previous_event_id = get_last_event_id() event.triggered_by_event_id = get_triggering_event_id() event.emission_sequence = get_next_emission_sequence() @@ -457,6 +452,15 @@ class CrewAIEventsBus: sync_handlers = self._sync_handlers.get(event_type, frozenset()) async_handlers = self._async_handlers.get(event_type, frozenset()) + # Skip executor initialization if no handlers exist for this event + if not sync_handlers and not async_handlers: + return None + + # Lazily initialize executor and event loop only when handlers exist + self._ensure_executor_initialized() + # Track that we have pending events for flush optimization + self._has_pending_events = True + if has_dependencies: return self._track_future( asyncio.run_coroutine_threadsafe( diff --git a/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py b/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py index c35530dec..25774b3e4 100644 --- a/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py +++ b/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py @@ -17,7 +17,7 @@ from crewai.events.listeners.tracing.first_time_trace_handler import ( from crewai.events.listeners.tracing.trace_batch_manager import TraceBatchManager from crewai.events.listeners.tracing.types import TraceEvent from crewai.events.listeners.tracing.utils import ( - is_tracing_enabled, + is_tracing_enabled_in_context, safe_serialize_to_dict, should_auto_collect_first_time_traces, should_enable_tracing, @@ -203,7 +203,8 @@ class TraceCollectionListener(BaseEventListener): # Skip registration entirely if tracing is disabled and not first-time user # This avoids overhead of 50+ handler registrations when tracing won't be used - if not should_enable_tracing() and not should_auto_collect_first_time_traces(): + # Also check is_tracing_enabled_in_context() so per-run overrides (Crew(tracing=True)) still work + if not should_enable_tracing() and not is_tracing_enabled_in_context() and not should_auto_collect_first_time_traces(): self._listeners_setup = True return diff --git a/lib/crewai/src/crewai/events/listeners/tracing/utils.py b/lib/crewai/src/crewai/events/listeners/tracing/utils.py index e2c43e5b3..545892d20 100644 --- a/lib/crewai/src/crewai/events/listeners/tracing/utils.py +++ b/lib/crewai/src/crewai/events/listeners/tracing/utils.py @@ -489,7 +489,16 @@ def _is_interactive_terminal() -> bool: """ import sys - return sys.stdin.isatty() + try: + stdin = getattr(sys, 'stdin', None) + if stdin is None: + return False + isatty = getattr(stdin, 'isatty', None) + if not callable(isatty): + return False + return bool(isatty()) + except Exception: + return False def prompt_user_for_trace_viewing(timeout_seconds: int = 20) -> bool: