Add verbose flag to EventListener for controlled logging

This commit is contained in:
Lorenze Jay
2025-03-11 08:43:56 -07:00
parent f2d53350d8
commit 7c46dce2f7
3 changed files with 365 additions and 338 deletions

View File

@@ -248,7 +248,10 @@ class Crew(BaseModel):
@model_validator(mode="after") @model_validator(mode="after")
def set_private_attrs(self) -> "Crew": def set_private_attrs(self) -> "Crew":
"""Set private attributes.""" """Set private attributes."""
from crewai.utilities.events.event_listener import EventListener
self._cache_handler = CacheHandler() self._cache_handler = CacheHandler()
EventListener().verbose = self.verbose
self._logger = Logger(verbose=self.verbose) self._logger = Logger(verbose=self.verbose)
if self.output_log_file: if self.output_log_file:
self._file_handler = FileHandler(self.output_log_file) self._file_handler = FileHandler(self.output_log_file)

View File

@@ -5,6 +5,8 @@ from crewai.utilities.events.crewai_event_bus import CrewAIEventsBus, crewai_eve
class BaseEventListener(ABC): class BaseEventListener(ABC):
verbose: bool = False
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.setup_listeners(crewai_event_bus) self.setup_listeners(crewai_event_bus)

View File

@@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from io import StringIO from io import StringIO
from typing import Any, Dict from typing import Any, Dict, Optional
from pydantic import Field, PrivateAttr from pydantic import Field, PrivateAttr
from rich.console import Console from rich.console import Console
@@ -112,7 +112,7 @@ class EventListener(BaseEventListener):
prefix: str, prefix: str,
name: str, name: str,
style: str = "blue", style: str = "blue",
status: str = None, status: Optional[str] = None,
) -> None: ) -> None:
"""Update tree label with consistent formatting.""" """Update tree label with consistent formatting."""
label = Text() label = Text()
@@ -130,19 +130,23 @@ class EventListener(BaseEventListener):
# ----------- METHODS ----------- # ----------- METHODS -----------
def on_crew_start(self, source: Any, event: Any) -> None: def on_crew_start(self, source: Any, event: Any) -> None:
# Create the crew tree that will hold tasks if self.verbose:
self.current_crew_tree = Tree( self.current_crew_tree = Tree(
Text("🚀 Crew: ", style="cyan bold") + Text(event.crew_name, style="cyan") Text("🚀 Crew: ", style="cyan bold")
+ Text(event.crew_name, style="cyan")
) )
content = Text() content = self._create_status_content(
content.append(f"NAME: {event.crew_name}", style="white") "Crew Execution Started",
content.append(f"\nID: {source.id}", style="blue") event.crew_name,
"cyan",
ID=source.id,
)
panel = self._create_panel(content, "Crew Execution Started", "cyan") panel = self._create_panel(content, "Crew Execution Started", "cyan")
self.console.print(panel) self.console.print(panel)
self.console.print() # Add spacing self.console.print()
self._telemetry.crew_execution_span(source, event.inputs) self._telemetry.crew_execution_span(source, event.inputs)
# ----------- CREW EVENTS ----------- # ----------- CREW EVENTS -----------
@@ -157,28 +161,24 @@ class EventListener(BaseEventListener):
# Handle telemetry # Handle telemetry
final_string_output = event.output.raw final_string_output = event.output.raw
self._telemetry.end_crew(source, final_string_output) self._telemetry.end_crew(source, final_string_output)
if self.verbose:
if self.current_crew_tree: if self.current_crew_tree:
# Update crew tree label to show completion self._update_tree_label(
crew_content = Text() self.current_crew_tree,
crew_content.append("✅ Crew: ", style="green bold") "✅ Crew:",
crew_content.append(event.crew_name or "Crew", style="green") event.crew_name or "Crew",
self.current_crew_tree.label = crew_content "green",
)
# Create completion panel
completion_content = Text() completion_content = self._create_status_content(
completion_content.append( "Crew Execution Completed",
"Crew Execution Completed\n", style="green bold" event.crew_name or "Crew",
"green",
ID=source.id,
) )
completion_content.append("Name: ", style="white")
completion_content.append(f"{event.crew_name}\n", style="green")
completion_content.append("ID: ", style="white")
completion_content.append(str(source.id), style="blue")
# Show final tree and completion panel
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
panel = self._create_panel( panel = self._create_panel(
completion_content, "Crew Completion", "green" completion_content, "Crew Completion", "green"
) )
@@ -187,6 +187,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(CrewKickoffFailedEvent) @crewai_event_bus.on(CrewKickoffFailedEvent)
def on_crew_failed(source, event: CrewKickoffFailedEvent): def on_crew_failed(source, event: CrewKickoffFailedEvent):
if self.verbose:
if self.current_crew_tree: if self.current_crew_tree:
# Update crew tree label to show failure # Update crew tree label to show failure
crew_content = Text() crew_content = Text()
@@ -212,7 +213,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(CrewTestFailedEvent) @crewai_event_bus.on(CrewTestFailedEvent)
def on_crew_test_failed(source, event: CrewTestFailedEvent): def on_crew_test_failed(source, event: CrewTestFailedEvent):
# Create test failure content if self.verbose:
failure_content = Text() failure_content = Text()
failure_content.append("❌ Crew Test Failed\n", style="red bold") failure_content.append("❌ Crew Test Failed\n", style="red bold")
failure_content.append("Crew: ", style="white") failure_content.append("Crew: ", style="white")
@@ -238,7 +239,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(CrewTrainFailedEvent) @crewai_event_bus.on(CrewTrainFailedEvent)
def on_crew_train_failed(source, event: CrewTrainFailedEvent): def on_crew_train_failed(source, event: CrewTrainFailedEvent):
# Create training failure content if self.verbose:
failure_content = Text() failure_content = Text()
failure_content.append("❌ Crew Training Failed\n", style="red bold") failure_content.append("❌ Crew Training Failed\n", style="red bold")
failure_content.append("Crew: ", style="white") failure_content.append("Crew: ", style="white")
@@ -255,7 +256,7 @@ class EventListener(BaseEventListener):
span = self._telemetry.task_started(crew=source.agent.crew, task=source) span = self._telemetry.task_started(crew=source.agent.crew, task=source)
self.execution_spans[source] = span self.execution_spans[source] = span
# Create task content if self.verbose:
task_content = Text() task_content = Text()
task_content.append("📋 Task: ", style="yellow bold") task_content.append("📋 Task: ", style="yellow bold")
task_content.append("\n Assigned to: ", style="white") task_content.append("\n Assigned to: ", style="white")
@@ -281,7 +282,7 @@ class EventListener(BaseEventListener):
self._telemetry.task_ended(span, source, source.agent.crew) self._telemetry.task_ended(span, source, source.agent.crew)
self.execution_spans[source] = None self.execution_spans[source] = None
# Create completion content if self.verbose:
completion_content = Text() completion_content = Text()
completion_content.append("✅ Task Completed\n", style="green bold") completion_content.append("✅ Task Completed\n", style="green bold")
completion_content.append(f"Task: {str(source.id)}", style="white") completion_content.append(f"Task: {str(source.id)}", style="white")
@@ -290,18 +291,20 @@ class EventListener(BaseEventListener):
# Update the tree if it exists # Update the tree if it exists
if self.current_crew_tree: if self.current_crew_tree:
# Find the task branch and update it with completion status
for branch in self.current_crew_tree.children: for branch in self.current_crew_tree.children:
if source.description in branch.label: if source.description in branch.label:
branch.label = Text("", style="green bold") + branch.label branch.label = (
Text("", style="green bold") + branch.label
)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
break break
# Always show completion panel panel = self._create_panel(
panel = self._create_panel(completion_content, "Task Completion", "green") completion_content, "Task Completion", "green"
)
self.console.print(panel) self.console.print(panel)
self.console.print() # Add spacing self.console.print()
@crewai_event_bus.on(TaskFailedEvent) @crewai_event_bus.on(TaskFailedEvent)
def on_task_failed(source, event: TaskFailedEvent): def on_task_failed(source, event: TaskFailedEvent):
@@ -311,7 +314,7 @@ class EventListener(BaseEventListener):
self._telemetry.task_ended(span, source, source.agent.crew) self._telemetry.task_ended(span, source, source.agent.crew)
self.execution_spans[source] = None self.execution_spans[source] = None
# Create failure content if self.verbose:
failure_content = Text() failure_content = Text()
failure_content.append("❌ Task Failed\n", style="red bold") failure_content.append("❌ Task Failed\n", style="red bold")
failure_content.append("Task: ", style="white") failure_content.append("Task: ", style="white")
@@ -338,31 +341,33 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(AgentExecutionStartedEvent) @crewai_event_bus.on(AgentExecutionStartedEvent)
def on_agent_execution_started(source, event: AgentExecutionStartedEvent): def on_agent_execution_started(source, event: AgentExecutionStartedEvent):
if self.verbose:
if self.current_task_branch: if self.current_task_branch:
# Create agent execution branch # Create agent execution branch with empty label
agent_content = Text() self.current_agent_branch = self.current_task_branch.add("")
agent_content.append("🤖 Agent: ", style="green bold") self._update_tree_label(
agent_content.append(event.agent.role, style="green") self.current_agent_branch,
agent_content.append("\n Status: ", style="white") "🤖 Agent:",
agent_content.append("In Progress", style="blue bold") event.agent.role,
"green",
"In Progress",
)
# Create a branch for the agent's activities
self.current_agent_branch = self.current_task_branch.add(agent_content)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(AgentExecutionCompletedEvent) @crewai_event_bus.on(AgentExecutionCompletedEvent)
def on_agent_execution_completed(source, event: AgentExecutionCompletedEvent): def on_agent_execution_completed(source, event: AgentExecutionCompletedEvent):
if self.verbose:
if self.current_agent_branch: if self.current_agent_branch:
# Update agent branch to show completion self._update_tree_label(
agent_content = Text() self.current_agent_branch,
agent_content.append("🤖 Agent: ", style="green bold") "🤖 Agent:",
agent_content.append(event.agent.role, style="green") event.agent.role,
agent_content.append("\n Status: ", style="white") "green",
agent_content.append("✅ Completed", style="green bold") "✅ Completed",
)
# Update the agent branch label
self.current_agent_branch.label = agent_content
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@@ -372,11 +377,10 @@ class EventListener(BaseEventListener):
def on_flow_created(source, event: FlowCreatedEvent): def on_flow_created(source, event: FlowCreatedEvent):
self._telemetry.flow_creation_span(event.flow_name) self._telemetry.flow_creation_span(event.flow_name)
# Create flow content for panel if self.verbose:
content = Text() content = self._create_status_content(
content.append("🌊 Starting Flow Execution\n\n", style="blue bold") "Starting Flow Execution", event.flow_name, "blue"
content.append("Name: ", style="white") )
content.append(event.flow_name, style="blue")
panel = self._create_panel(content, "Flow Execution", "blue") panel = self._create_panel(content, "Flow Execution", "blue")
@@ -406,14 +410,15 @@ class EventListener(BaseEventListener):
event.flow_name, list(source._methods.keys()) event.flow_name, list(source._methods.keys())
) )
# Create flow tree with status if self.verbose:
flow_label = Text() self.current_flow_tree = Tree("")
flow_label.append("🌊 Flow: ", style="blue bold") self._update_tree_label(
flow_label.append(event.flow_name, style="blue") self.current_flow_tree,
flow_label.append("\n Status: ", style="white") "🌊 Flow:",
flow_label.append("In Progress", style="yellow") event.flow_name,
"blue",
self.current_flow_tree = Tree(flow_label) "In Progress",
)
# Add initial thinking state # Add initial thinking state
self.current_flow_tree.add(Text("🧠 Initializing...", style="yellow")) self.current_flow_tree.add(Text("🧠 Initializing...", style="yellow"))
@@ -424,19 +429,21 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(FlowFinishedEvent) @crewai_event_bus.on(FlowFinishedEvent)
def on_flow_finished(source, event: FlowFinishedEvent): def on_flow_finished(source, event: FlowFinishedEvent):
if self.verbose:
if self.current_flow_tree: if self.current_flow_tree:
# Update flow tree label to show completion self._update_tree_label(
self.current_flow_tree.label = Text( self.current_flow_tree,
"✅ Flow Finished: ", style="green bold" "✅ Flow Finished:",
) + Text(event.flow_name, style="green") event.flow_name,
"green",
)
# Create completion content content = self._create_status_content(
content = Text() "Flow Execution Completed",
content.append("Flow Execution Completed\n", style="green bold") event.flow_name,
content.append("Name: ", style="white") "green",
content.append(f"{event.flow_name}\n", style="green") ID=source.flow_id,
content.append("ID: ", style="white") )
content.append(source.flow_id, style="blue")
panel = self._create_panel(content, "Flow Completion", "green") panel = self._create_panel(content, "Flow Completion", "green")
self.console.print(panel) self.console.print(panel)
@@ -444,14 +451,15 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(MethodExecutionStartedEvent) @crewai_event_bus.on(MethodExecutionStartedEvent)
def on_method_execution_started(source, event: MethodExecutionStartedEvent): def on_method_execution_started(source, event: MethodExecutionStartedEvent):
if self.verbose:
if self.current_flow_tree: if self.current_flow_tree:
# Find and update the method branch # Find and update the method branch
for branch in self.current_flow_tree.children: for branch in self.current_flow_tree.children:
if event.method_name in branch.label: if event.method_name in branch.label:
self.current_method_branch = branch self.current_method_branch = branch
branch.label = Text("🔄 Running: ", style="yellow bold") + Text( branch.label = Text(
event.method_name, style="yellow" "🔄 Running: ", style="yellow bold"
) ) + Text(event.method_name, style="yellow")
break break
self.console.print(self.current_flow_tree) self.console.print(self.current_flow_tree)
@@ -459,6 +467,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(MethodExecutionFinishedEvent) @crewai_event_bus.on(MethodExecutionFinishedEvent)
def on_method_execution_finished(source, event: MethodExecutionFinishedEvent): def on_method_execution_finished(source, event: MethodExecutionFinishedEvent):
if self.verbose:
if self.current_method_branch: if self.current_method_branch:
# Update method status # Update method status
self.current_method_branch.label = Text( self.current_method_branch.label = Text(
@@ -469,8 +478,8 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(MethodExecutionFailedEvent) @crewai_event_bus.on(MethodExecutionFailedEvent)
def on_method_execution_failed(source, event: MethodExecutionFailedEvent): def on_method_execution_failed(source, event: MethodExecutionFailedEvent):
if self.verbose:
if self.current_method_branch: if self.current_method_branch:
# Update method status to show failure
self.current_method_branch.label = Text( self.current_method_branch.label = Text(
"❌ Failed: ", style="red bold" "❌ Failed: ", style="red bold"
) + Text(event.method_name, style="red") ) + Text(event.method_name, style="red")
@@ -481,6 +490,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(ToolUsageStartedEvent) @crewai_event_bus.on(ToolUsageStartedEvent)
def on_tool_usage_started(source, event: ToolUsageStartedEvent): def on_tool_usage_started(source, event: ToolUsageStartedEvent):
if self.verbose:
# Create tool usage content # Create tool usage content
tool_content = Text() tool_content = Text()
tool_content.append("🔧 Using ", style="yellow bold") tool_content.append("🔧 Using ", style="yellow bold")
@@ -488,13 +498,15 @@ class EventListener(BaseEventListener):
# Add to tree under the agent branch # Add to tree under the agent branch
if self.current_agent_branch: if self.current_agent_branch:
self.current_tool_branch = self.current_agent_branch.add(tool_content) self.current_tool_branch = self.current_agent_branch.add(
tool_content
)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(ToolUsageFinishedEvent) @crewai_event_bus.on(ToolUsageFinishedEvent)
def on_tool_usage_finished(source, event: ToolUsageFinishedEvent): def on_tool_usage_finished(source, event: ToolUsageFinishedEvent):
# Create completion content if self.verbose:
completion_content = Text() completion_content = Text()
completion_content.append("🔧 Used ", style="green bold") completion_content.append("🔧 Used ", style="green bold")
completion_content.append(event.tool_name, style="green") completion_content.append(event.tool_name, style="green")
@@ -507,7 +519,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(ToolUsageErrorEvent) @crewai_event_bus.on(ToolUsageErrorEvent)
def on_tool_usage_error(source, event: ToolUsageErrorEvent): def on_tool_usage_error(source, event: ToolUsageErrorEvent):
# Create tool error content if self.verbose:
error_content = Text() error_content = Text()
error_content.append("🔧 Tool Failed: ", style="red bold") error_content.append("🔧 Tool Failed: ", style="red bold")
error_content.append(event.tool_name, style="red") error_content.append(event.tool_name, style="red")
@@ -521,7 +533,8 @@ class EventListener(BaseEventListener):
# Show error panel # Show error panel
panel = self._create_panel( panel = self._create_panel(
Text( Text(
f"Tool usage failed: {event.tool_name}: {event.error}", style="red" f"Tool usage failed: {event.tool_name}: {event.error}",
style="red",
), ),
"Tool Error", "Tool Error",
"red", "red",
@@ -533,19 +546,21 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(LLMCallStartedEvent) @crewai_event_bus.on(LLMCallStartedEvent)
def on_llm_call_started(source, event: LLMCallStartedEvent): def on_llm_call_started(source, event: LLMCallStartedEvent):
# Create simple LLM call content if self.verbose:
llm_content = Text() llm_content = Text()
llm_content.append("🧠 Thinking...", style="blue bold") llm_content.append("🧠 Thinking...", style="blue bold")
# Add to tree under the agent branch # Add to tree under the agent branch
if self.current_agent_branch: if self.current_agent_branch:
self.current_tool_branch = self.current_agent_branch.add(llm_content) self.current_tool_branch = self.current_agent_branch.add(
llm_content
)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(LLMCallCompletedEvent) @crewai_event_bus.on(LLMCallCompletedEvent)
def on_llm_call_completed(source, event: LLMCallCompletedEvent): def on_llm_call_completed(source, event: LLMCallCompletedEvent):
# Create simple completion content if self.verbose:
completion_content = Text() completion_content = Text()
completion_content.append("✨ Done", style="green bold") completion_content.append("✨ Done", style="green bold")
@@ -557,7 +572,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(LLMCallFailedEvent) @crewai_event_bus.on(LLMCallFailedEvent)
def on_llm_call_failed(source, event: LLMCallFailedEvent): def on_llm_call_failed(source, event: LLMCallFailedEvent):
# Create LLM error content if self.verbose:
error_content = Text() error_content = Text()
error_content.append("❌ LLM Call Failed\n", style="red bold") error_content.append("❌ LLM Call Failed\n", style="red bold")
error_content.append("Error: ", style="white") error_content.append("Error: ", style="white")
@@ -565,7 +580,9 @@ class EventListener(BaseEventListener):
# Update under the agent branch if it exists # Update under the agent branch if it exists
if self.current_tool_branch: if self.current_tool_branch:
self.current_tool_branch.label = Text("❌ LLM Failed", style="red bold") self.current_tool_branch.label = Text(
"❌ LLM Failed", style="red bold"
)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@@ -595,7 +612,7 @@ class EventListener(BaseEventListener):
event.eval_llm or "", event.eval_llm or "",
) )
# Create test content for panel if self.verbose:
content = Text() content = Text()
content.append("🧪 Starting Crew Test\n\n", style="blue bold") content.append("🧪 Starting Crew Test\n\n", style="blue bold")
content.append("Crew: ", style="white") content.append("Crew: ", style="white")
@@ -626,6 +643,7 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(CrewTestCompletedEvent) @crewai_event_bus.on(CrewTestCompletedEvent)
def on_crew_test_completed(source, event: CrewTestCompletedEvent): def on_crew_test_completed(source, event: CrewTestCompletedEvent):
if self.verbose:
if self.current_flow_tree: if self.current_flow_tree:
# Update test tree label to show completion # Update test tree label to show completion
test_label = Text() test_label = Text()
@@ -647,13 +665,17 @@ class EventListener(BaseEventListener):
# Create completion panel # Create completion panel
completion_content = Text() completion_content = Text()
completion_content.append("Test Execution Completed\n", style="green bold") completion_content.append(
"Test Execution Completed\n", style="green bold"
)
completion_content.append("Crew: ", style="white") completion_content.append("Crew: ", style="white")
completion_content.append(f"{event.crew_name}\n", style="green") completion_content.append(f"{event.crew_name}\n", style="green")
completion_content.append("Status: ", style="white") completion_content.append("Status: ", style="white")
completion_content.append("All tests passed", style="green") completion_content.append("All tests passed", style="green")
panel = self._create_panel(completion_content, "Test Completion", "green") panel = self._create_panel(
completion_content, "Test Completion", "green"
)
self.console.print(panel) self.console.print(panel)
self.console.print() self.console.print()