symfonycasts/messenger-monitor-bundle
A Symfony bundle that adds a Telescope-style dashboard for Symfony Messenger, letting you inspect dispatched, handled, and failed messages, transports, and handler performance in real time, making it easier to debug async workflows and background jobs.
Install: composer require --dev symfonycasts/messenger-monitor-bundle. It's a dev/debug-style tool, so lean toward --dev unless you intentionally want it in a staging/prod image. With Symfony Flex the bundle registers itself in config/bundles.php; otherwise add SymfonyCasts\MessengerMonitorBundle\MessengerMonitorBundle manually.
Look first at: the bundle README (config keys and route), then your existing config/packages/messenger.yaml to see which transport service IDs/queue names exist. The dashboard only reflects transports you explicitly tell it about.
Configure the transports to track in config/packages/messenger_monitor.yaml:
# config/packages/messenger_monitor.yaml
messenger_monitor:
# map of transport service / queue name to display in the dashboard
transports:
- async
- failed
Use the same transport names as your framework.messenger.transports configuration. For multi-queue transports (e.g. a Doctrine transport with several queues), make sure you're pointing at the queue you actually want counted.
Open the dashboard at the configured route (default is typically /messenger-monitor; check the README/path option for your version). You should see a card per tracked transport with a live-ish message-count snapshot.
First use case: run a worker (bin/console messenger:consume async) in one terminal and the dashboard in another. Push a few messages into the queue and refresh to confirm you can watch depth go up and drain down, and that your failed transport shows anything that blows up. That is the 10-minute sanity loop the bundle is built for.
Local dev feedback loop: keep the dashboard open at the configured path while you work. Instead of tailing worker logs or running messenger:failed:show after every dispatch, you get a per-transport readout of backlog and failures. Pair it with a messenger:consume watcher (e.g. symfony console + --time-limit) so you can watch queues drain in real time.
Staging smoke-test dashboard: mount it in staging behind the firewall and use it as the first place you look after a deploy. A sudden jump in the failed transport or a growing async backlog is an immediate "is the worker running?" signal.
Protect the route before it leaves local:
# config/packages/security.yaml
security:
access_control:
- { path: ^/messenger-monitor, roles: ROLE_ADMIN }
Or restrict by access_control IP/firewall config if you don't have an admin role. The dashboard exposes operational info (transport names, queue depths), so treat it as an internal tool.
Track the failed transport deliberately: failed messages are the highest-signal queue. If your project uses a separate failed transport (failure_transport: failed), add it to the monitor so retries/messenger:failed:retry can be triaged from the dashboard rather than memorizing CLI commands.
Environment-specific config: enable the bundle (and route) only in dev/staging:
# config/packages/dev/messenger_monitor.yaml
messenger_monitor:
path: /_monitoring/messenger
and when@dev/when@staging in the main config. This keeps the route out of production without maintaining a second bundle list.
Multiple transports as a quick capacity view: if you split async, priority, and failed, the dashboard's side-by-side cards are a cheap way to spot one queue starving while another backs up — something raw messenger:stats output doesn't highlight.
Extension point for unsupported transports: the bundle counts messages by asking the transport/queue for stats. If a custom transport doesn't support that (or you want to add derived metrics), look for the bundle's monitor/stats extension interface and register your own service for that transport rather than patching vendor code.
Pair, don't replace: use this for the "is something obviously wrong right now" check, and keep messenger:failed:show --stats, messenger:failed:retry, and your logs/Sentry for forensics. The dashboard is a snapshot, not a history.
messenger_messages table. A custom transport may return nothing — if a card shows no count, it's usually the transport, not the bundle.messenger.yaml queue names before assuming the bundle is broken.async count is normal under load. The useful signal is trend and failed count. Don't configure alerts off the dashboard's raw number; correlate with worker health.config/routes / bundle recipe, set access_control, and make sure the path doesn't collide with an existing route in your app.messenger:failed:show / messenger:failed:retry, or a proper message-monitor UI. Don't expect this bundle to replace that workflow.bin/console cache:clear. Config keys differ slightly across bundle versions, so if a transport card doesn't appear, re-check the key names in the README for the installed version before assuming a bug — the config shape has changed between releases.getMessageCount()-style stats aren't available on all transports, which silently degrades the dashboard. Pin a bundle version that matches your Symfony minor.framework.messenger.transports, (3) the transport service is public/accessible to the bundle, and (4) you cleared cache. That covers most "nothing renders" reports.How can I help you explore Laravel packages today?