WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.066 --> 00:00:02.366 align:middle
Hey, you're still here?

00:00:02.606 --> 00:00:05.136 align:middle
Great! Let's do one final bonus chapter!

00:00:05.646 --> 00:00:08.626 align:middle
When you have a bunch of messages and
schedules running in the background,

00:00:08.886 --> 00:00:10.336 align:middle
it can be hard to know what's happening.

00:00:10.776 --> 00:00:11.856 align:middle
Are my workers running?

00:00:12.086 --> 00:00:13.236 align:middle
Is my schedule running?

00:00:13.466 --> 00:00:14.476 align:middle
And where is it running to?

00:00:14.956 --> 00:00:15.896 align:middle
What about failures?

00:00:15.896 --> 00:00:17.466 align:middle
I mean, we have logs, but...

00:00:17.786 --> 00:00:23.056 align:middle
logs. Instead, let's explore a cool bundle
that gives us a UI to get some visibility

00:00:23.056 --> 00:00:25.556 align:middle
on what's going on with our
army of worker robots!

00:00:26.096 --> 00:00:34.136 align:middle
At your terminal, run: composer require
zenstruck/messenger-monitor-bundle It's asking

00:00:34.136 --> 00:00:36.186 align:middle
to install a recipe, say yes.

00:00:38.056 --> 00:00:40.326 align:middle
Jump back to our IDE and see what was added.

00:00:41.036 --> 00:00:43.866 align:middle
First, a src/Schedule.php was added.

00:00:44.336 --> 00:00:45.766 align:middle
This is unrelated to this bundle.

00:00:46.286 --> 00:00:49.036 align:middle
Since the last chapter, where
we added the Symfony Scheduler,

00:00:49.246 --> 00:00:52.296 align:middle
it now has an official recipe
that adds a default schedule.

00:00:52.636 --> 00:00:54.766 align:middle
Since we already have one, delete this file.

00:00:55.616 --> 00:01:00.816 align:middle
A new controller was added: src/Controller/Admin
/MessengerMonitorController.php.

00:01:00.816 --> 00:01:04.906 align:middle
This is a stub to enable the bundle's UI.

00:01:04.906 --> 00:01:08.136 align:middle
It extends this BaseMessengerMonitorController
from the bundle

00:01:08.346 --> 00:01:11.596 align:middle
and adds a route prefix of /admin/messenger.

00:01:12.156 --> 00:01:15.336 align:middle
It also adds this #[IsGranted('ROLE_ADMIN')]
attribute.

00:01:15.726 --> 00:01:17.826 align:middle
This is super important for your real apps.

00:01:17.996 --> 00:01:22.436 align:middle
You only want site admins to access the
UI as it shows sensitive information.

00:01:22.956 --> 00:01:26.616 align:middle
We don't have security configured in
this app, so I'll just remove this line:

00:01:28.096 --> 00:01:33.036 align:middle
src/Entity/ProcessedMessage.php is
a new entity added by the recipe.

00:01:33.616 --> 00:01:37.546 align:middle
This is also a stub that extends
this BaseProcessedMessage class

00:01:37.716 --> 00:01:38.866 align:middle
and adds an ID column.

00:01:39.456 --> 00:01:42.286 align:middle
This is used to track the history
of your messenger messages.

00:01:42.696 --> 00:01:46.326 align:middle
For every message processed, a new
one of these entities is persisted.

00:01:46.956 --> 00:01:49.666 align:middle
Don't worry though, this is
done in your worker process,

00:01:49.666 --> 00:01:51.436 align:middle
so it won't slow down your app's frontend.

00:01:52.156 --> 00:01:55.096 align:middle
Since we have a new entity, we
should be adding a migration,

00:01:55.296 --> 00:01:57.796 align:middle
but I don't have migrations
configured for this project.

00:01:58.256 --> 00:02:03.506 align:middle
So in your terminal, run: symfony
console doctrine:schema:update --

00:02:03.616 --> 00:02:08.726 align:middle
force Before we check out the UI, the
bundle has two optional dependencies

00:02:08.726 --> 00:02:09.696 align:middle
that I want to install.

00:02:10.126 --> 00:02:18.296 align:middle
First: composer require knplabs/knp-time-bundle
This makes the UI's timestamps human-readable -

00:02:18.416 --> 00:02:19.596 align:middle
like "4 minutes ago".

00:02:20.336 --> 00:02:24.696 align:middle
Next: composer require
lorisleiva/cron-translator

00:02:25.286 --> 00:02:28.126 align:middle
Since we're using cron expressions
for our scheduled tasks,

00:02:28.416 --> 00:02:30.196 align:middle
this package makes them human-readable.

00:02:30.466 --> 00:02:36.636 align:middle
So instead of "11 2 * * *", it will
display this as "every day at 2:11 AM".

00:02:37.016 --> 00:02:39.166 align:middle
Slick! We're ready to go!

00:02:39.386 --> 00:02:46.936 align:middle
Start the server with: symfony serve -d Jump
over to the browser and visit: /admin/messenger.

00:02:47.226 --> 00:02:49.096 align:middle
This is the Messenger Monitor dashboard!

00:02:49.766 --> 00:02:52.576 align:middle
This first widget shows running
workers and their status.

00:02:52.966 --> 00:02:56.276 align:middle
We can see we have 1 worker
running for our async transport.

00:02:56.646 --> 00:02:59.866 align:middle
This is the one we configured to
run with our Symfony CLI server.

00:03:00.426 --> 00:03:04.266 align:middle
Below, we see our available
transports, how many messages are queued,

00:03:04.506 --> 00:03:05.966 align:middle
and how many workers are running them.

00:03:06.576 --> 00:03:09.696 align:middle
Notice it shows our scheduler_default
transport as not running.

00:03:10.056 --> 00:03:12.766 align:middle
This is expected, as we didn't
configure it to run locally.

00:03:13.496 --> 00:03:17.096 align:middle
Below that, we have a snapshot of
statistics for the last 24 hours.

00:03:17.616 --> 00:03:20.836 align:middle
On the right, we will see the
last 15 messages processed.

00:03:21.226 --> 00:03:22.596 align:middle
This is of course empty right now.

00:03:23.306 --> 00:03:26.116 align:middle
All these widgets autorefresh every 5 seconds.

00:03:26.616 --> 00:03:27.936 align:middle
Let's create some history!

00:03:28.426 --> 00:03:31.786 align:middle
In the top bar, click on
Schedule (note the icon is red

00:03:31.786 --> 00:03:33.796 align:middle
to further indicate the schedule isn't running).

00:03:34.356 --> 00:03:37.356 align:middle
This is kind of a "more advanced
debug:schedule command".

00:03:37.666 --> 00:03:39.536 align:middle
We see our single scheduled task:

00:03:39.716 --> 00:03:43.166 align:middle
RunCommandMessage for
app:send-booking-reminders.

00:03:43.556 --> 00:03:47.736 align:middle
It uses a CronExpressionTrigger
to run "every day at 2:11 AM".

00:03:48.456 --> 00:03:52.236 align:middle
0 runs so far but we can run it
manually by clicking "Trigger"...

00:03:52.546 --> 00:03:54.366 align:middle
and selecting our async transport.

00:03:55.166 --> 00:03:56.336 align:middle
Jump back to the dashboard.

00:03:57.066 --> 00:04:02.096 align:middle
It ran successfully, took 58ms,
and consumed 31MB of memory.

00:04:02.626 --> 00:04:04.856 align:middle
Click "Details" to see even more information!

00:04:05.166 --> 00:04:08.366 align:middle
"Time in Queue", "Time to Handle", timestamps...

00:04:08.456 --> 00:04:09.406 align:middle
lots of good stuff.

00:04:09.936 --> 00:04:12.626 align:middle
These tags are super helpful
for filtering messages.

00:04:13.006 --> 00:04:16.536 align:middle
You can add your own tags but some
are added by the bundle: manual,

00:04:16.746 --> 00:04:21.736 align:middle
because we "manually" ran a scheduled task,
schedule, because it was a scheduled task,

00:04:21.986 --> 00:04:25.266 align:middle
schedule:default, because it's
part of our default schedule.

00:04:25.706 --> 00:04:29.996 align:middle
This schedule:default:&lt;hash&gt; is the
unique ID for this scheduled task.

00:04:30.926 --> 00:04:33.736 align:middle
On the right here is the "result"
of the message "handler" -

00:04:34.116 --> 00:04:36.836 align:middle
in this case, RunCommandMessageHandler.

00:04:37.326 --> 00:04:40.136 align:middle
Different handlers have different
results (some have none).

00:04:40.626 --> 00:04:43.766 align:middle
For this one, the result is the
command's exit code and output.

00:04:44.556 --> 00:04:48.966 align:middle
Sent 0 booking reminders Let's run
this task again, but this time,

00:04:48.966 --> 00:04:50.866 align:middle
with a booking that needs a reminder sent.

00:04:51.456 --> 00:04:53.626 align:middle
Back in your terminal, reload our fixtures:

00:04:53.866 --> 00:04:58.896 align:middle
symfony console doctrine:fixtures:load
Back to the browser.

00:04:59.256 --> 00:05:01.536 align:middle
The dashboard is empty now but that's expected:

00:05:01.916 --> 00:05:04.536 align:middle
reloading our fixtures also
cleared our message history.

00:05:05.036 --> 00:05:08.136 align:middle
Click "Schedule", then "Trigger"
on our "async" transport.

00:05:08.726 --> 00:05:11.466 align:middle
Back on the dashboard, we have 2 messages now.

00:05:11.836 --> 00:05:14.696 align:middle
RunCommandMessage again but click its "Details":

00:05:15.056 --> 00:05:20.416 align:middle
Sent 1 booking reminders Now our
second message: SendEmailMessage.

00:05:20.936 --> 00:05:22.516 align:middle
This was dispatched by the command.

00:05:22.956 --> 00:05:26.616 align:middle
Click its "Details" to see
email-related information for its results.

00:05:27.046 --> 00:05:28.866 align:middle
Note the tag, booking_reminder.

00:05:29.336 --> 00:05:32.406 align:middle
The bundle automatically detected
that we were sending an email with a

00:05:32.406 --> 00:05:34.396 align:middle
"Mailer" tag, so it added it here.

00:05:35.286 --> 00:05:38.606 align:middle
In the top menu, you can click
"Transports" to see more details

00:05:38.606 --> 00:05:41.366 align:middle
on each one's pending messages (if applicable).

00:05:42.096 --> 00:05:46.066 align:middle
The failed transport shows failed
messages and gives you the option to retry

00:05:46.066 --> 00:05:48.026 align:middle
or remove them, right from the UI!

00:05:48.616 --> 00:05:53.366 align:middle
"History" is where we can filter messages:
Period, limit to a specific date range.

00:05:53.546 --> 00:05:55.916 align:middle
Transport, limit to a specific transport.

00:05:56.276 --> 00:05:58.986 align:middle
Status, show just successes or failures.

00:05:59.326 --> 00:06:03.366 align:middle
Schedule, whether to include or exclude
messages triggered by a schedule.

00:06:03.726 --> 00:06:06.166 align:middle
Message type, filter by message class.

00:06:06.646 --> 00:06:09.566 align:middle
"Statistics" shows a per-message-class
stat summary

00:06:09.566 --> 00:06:11.686 align:middle
and can be limited to a specific date-range.

00:06:12.286 --> 00:06:15.746 align:middle
As you can probably imagine, if
your app executes a lot of messages,

00:06:15.746 --> 00:06:17.736 align:middle
our history table can get really big.

00:06:18.346 --> 00:06:21.446 align:middle
The bundle provides some
commands to purge older messages.

00:06:22.066 --> 00:06:27.496 align:middle
In the bundle docs, scroll down to
"messenger:monitor:purge" and copy the command.

00:06:28.716 --> 00:06:30.126 align:middle
We need to schedule this...

00:06:30.346 --> 00:06:32.986 align:middle
but how? With Symfony Scheduler of course!

00:06:33.416 --> 00:06:41.066 align:middle
Open src/Scheduler/MainSchedule.php and add a
new task with -&gt;add(RecurringMessage::cron()).

00:06:42.006 --> 00:06:45.636 align:middle
Use #midnight so it runs daily
between midnight and 3am.

00:06:46.396 --> 00:06:49.306 align:middle
Add new RunCommandMessage()
and paste the command.

00:06:49.946 --> 00:06:54.206 align:middle
Add the -- exclude-schedules option:
This will purge messages older

00:06:54.206 --> 00:06:57.366 align:middle
than 30 days except messages
triggered by a schedule.

00:06:57.886 --> 00:07:02.266 align:middle
This is important because your scheduled tasks
might run once a month or even once a year.

00:07:02.686 --> 00:07:05.896 align:middle
This enables you to keep a history of
them regardless of their frequency.

00:07:06.576 --> 00:07:07.866 align:middle
We should still clean these up though.

00:07:08.216 --> 00:07:13.256 align:middle
So, back in the docs, copy a second
command: messenger:monitor:schedule:purge.

00:07:13.636 --> 00:07:19.966 align:middle
And in the schedule, add it with
-&gt;add(RecurringMessage::cron('#midnight',

00:07:20.646 --> 00:07:26.706 align:middle
new RunCommandMessage())) and paste: This will
purge the history of scheduled messages skipped

00:07:26.706 --> 00:07:30.326 align:middle
by the command above but keep
the last 10 runs of each.

00:07:30.866 --> 00:07:33.066 align:middle
Let's make sure these tasks
were added to our schedule.

00:07:33.466 --> 00:07:38.706 align:middle
Back in the browser, click "Schedule"
and here we go: our two new tasks.

00:07:39.206 --> 00:07:41.036 align:middle
For the task we ran manually earlier,

00:07:41.236 --> 00:07:45.166 align:middle
we can see the last run summary,
details, and even its history.

00:07:45.896 --> 00:07:46.646 align:middle
Ok friends!

00:07:46.806 --> 00:07:49.836 align:middle
That's a quick run-through of the
zenstruck/messenger-monitor-bundle.

00:07:50.306 --> 00:07:53.156 align:middle
Check out the docs for more
information on all it's features.

00:07:53.536 --> 00:07:55.466 align:middle
'Til next time, happy monitoring!

