事件总线与遥测
学习目标
理解 CrewAI 的事件总线架构——单例模式、双执行器、依赖图执行计划、事件懒加载,以及 OpenTelemetry 遥测的集成方式。
项目实践
CrewAIEventsBus 单例
crewai_event_bus: Final[CrewAIEventsBus] = CrewAIEventsBus()双执行器:
- Sync 处理器在
ThreadPoolExecutor(max_workers=10)执行 - Async 处理器在独立的后台
asyncio.EventLoop执行 - 延迟初始化:executor 和 event loop 在第一次
emit()时才创建,减少开销
读写锁:_rwlock: RWLock 保护 handler 注册/注销。
依赖图:通过 depends_on 注册 handler 依赖,build_execution_plan() 构建分层执行计划。执行计划缓存到 handler 变更。
事件类型层次
所有事件继承自 BaseEvent,包含:
event_id、parent_event_id、previous_event_id、triggered_by_event_id— 事件链追踪emission_sequence— 全局递增序列号(context variable)source_fingerprint、source_type— 来源标记
CrewAI 定义了 ~80+ 事件类型:Crew、Agent、Task、Flow、LLM、Tool、Memory、Knowledge、MCP、Skill、Checkpoint 等。
事件懒加载
__init__.py 使用 __getattr__ 实现事件的懒加载:
- 通过
_LAZY_EVENT_MAPPING字典延迟导入 - 避免启动时加载 ~12 个 Pydantic 模块及其传递依赖
- 首次引用某个事件类时才触发导入
重放机制
crewai_event_bus.replay(source, event) 方法:
- 不修改事件的
event_id和emission_sequence - 不重新记录事件到 event record
- 通过
_replayingcontext variable 通知 handler(有副作用的 handler 应跳过)
事件上下文与范围栈
event_context.py 维护一个 scope 栈,实现事件父子关系:
push_event_scope(event_id, event_type)/pop_event_scope()— 成对的 Started/Completed 事件VALID_EVENT_PAIRS验证 Started/Completed 配对是否匹配triggered_by_scope— 追踪因果链
OpenTelemetry 遥测
Telemetry 单例基于 OpenTelemetry:
- 发送目标:
https://telemetry.crewai.com:4319 - 可通过
OTEL_SDK_DISABLED=true、CREWAI_DISABLE_TELEMETRY=true、CREWAI_DISABLE_TRACKING=true禁用 SafeOTLPSpanExporter包装器捕获导出失败- 默认只发送元数据,
crew.share_crew=True才发送详细数据 - 信号处理器:SIGTERM/SIGINT/SIGHUP/SIGTSTP/SIGCONT
问题与规避
事件总线单例不支持多租户隔离
- 全局唯一的
crewai_event_bus不支持多租户隔离 - 对策:使用
scoped_handlers()上下文管理器提供临时隔离,测试间需要clear_all_global_hooks()
懒加载的首次引用延迟
- 首次引用某个事件时有导入开销
- 对策:在应用启动时预热导入(引用所有常用事件类)
遥测的隐私顾虑
- 即使默认只发送元数据,某些场景下仍需要完全禁用
- 对策:设置
CREWAI_DISABLE_TELEMETRY=true环境变量
设计取舍
单例事件总线 vs 可实例化事件总线
- 单例简化了事件注册和发射,全局共享
- 代价是不支持多租户隔离
scoped_handlers()提供临时隔离,但不如完全独立的事件总线彻底
事件懒加载 vs 预加载
- 懒加载减少启动开销,但首次引用时有延迟
- 对于 CLI 工具(启动即退出),懒加载是更优选择
- 对于长时运行的服务,预加载可能更合适
参考来源
- 源码验证:
lib/crewai/src/crewai/events/event_bus.py - 源码验证:
lib/crewai/src/crewai/events/base_events.py - 源码验证:
lib/crewai/src/crewai/events/__init__.py - 源码验证:
lib/crewai/src/crewai/telemetry/telemetry.py