直接继承 DataCollector 不行,因为其依赖 HTTP 请求周期而 RabbitMQ 消费者是命令行长期进程,无法触发 profiler;应改用 EventSubscriber + 自定义 DataCollectorInterface 实现,在 WorkerMessageHandledEvent 中更新指标,并配置模板与启用 profiler。

为什么直接继承 DataCollector 不行?
Symfony 的 DataCollector 是抽象类,但它的生命周期和使用场景有硬性约束:它只在 profiler 启用且当前请求进入 HTTP 生命周期时才被调用。RabbitMQ 消费者通常是命令行长期运行的守护进程(比如 php bin/console messenger:consume),根本不会触发 profiler 的 request cycle,所以直接写个类继承 DataCollector 并注册为服务,指标永远不会被收集或显示。
改用 EventSubscriber + 自定义 CollectorInterface 实现
真正可行的路径是绕过 DataCollector 的 HTTP 绑定,自己实现 Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface,再配合事件驱动手动注入数据。Messenger 组件在消费每条消息前后会派发 WorkerMessageReceivedEvent 和 WorkerMessageHandledEvent(v6.2+)或 MessageReceivedEvent/MessageHandledEvent(旧版),这是唯一可控的埋点时机。
- 定义一个普通服务类(不继承
DataCollector),实现DataCollectorInterface,重点实现collect()、getName()、reset() - 在
collect()中只做数据快照(如当前队列长度、累计处理数、最近 10 条耗时),不依赖$request或$response - 注册一个
EventSubscriber,监听WorkerMessageHandledEvent,更新你的 collector 实例里的计数器和耗时数组 - 把 collector 实例设为 public service,并在 profiler 的
data_collector配置中显式声明template和id
模板里怎么显示非 HTTP 场景的数据?
Profiler 的 UI 默认假设所有 collector 数据都来自一次请求,所以会尝试渲染 getPanelSummary() 和 getTemplate() 返回的 Twig 片段。你必须提供一个真实存在的 Twig 模板(如 @App/Collector/rabbitmq.html.twig),并在其中避免使用 profiler_dump() 或任何依赖 token 的函数 —— 因为命令行场景下 $collector->getProfile() 是 null。
- 模板里只读取你存的原始字段,例如
{{ collector.totalConsumed }}、{{ collector.avgProcessingTime|number_format(2) }} ms - 不要调用
collector.time或collector.memory—— 这些是 HTTP 请求专属字段,你的 collector 里没设它们 - 在配置中加
display: true,否则即使 collector 被调用,面板也不会出现在 profiler 左侧菜单
注意 Messenger 版本与事件名差异
不同 Symfony/Messenger 版本暴露的事件类完全不同,错配会导致监听失效,指标始终为 0:
- v6.2+:用
Symfony\Component\Messenger\Event\WorkerMessageHandledEvent - v6.1 及更早:用
Symfony\Component\Messenger\Event\MessageHandledEvent - 如果你用的是自定义 worker(非
messenger:consume),还要确认是否启用了event_bus: true(默认开启),否则事件根本不会派发 - 别忘了在
services.yaml中给你的 subscriber 加tags: [{ name: 'kernel.event_subscriber' }],否则监听器不会注册
最常被忽略的是:命令行运行时 profiler 默认关闭,必须显式启用 —— 在 .env 里设 APP_ENV=dev 且确保 framework.profiler.only_exceptions: false,否则即使 collector 正常工作,数据也进不了 profiler 存储。


















