Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Data Watcher Bundle Laravel Package

benjamin-rqt/data-watcher-bundle

Symfony bundle for database anomaly detection: define SQL or Doctrine checks, run them manually or on a cron schedule, store execution history, and send email notifications when anomalies are detected. Supports Symfony 6.3, 7.0 and 8.0, Messenger, Mailer and Twig.

View on GitHub
Deep Wiki
Context7

Getting Started

Because this is a Symfony bundle (not a Laravel package), the first practical step is confirming your project is on Symfony 6.3/7.0/8.0 with framework-bundle, messenger, mailer, twig-bundle, scheduler, and doctrine/dbal already installed. If you are in a Laravel codebase, stop here — there is no Laravel service provider, config publishing, or Mail/Queue integration to rely on.

Minimal flow to first value:

  1. Add the VCS repository and composer require benjamin-rqt/data-watcher-bundle.
  2. Ensure BenjaminRqt\DataWatcherBundle\DataWatcherBundle is registered in config/bundles.php (Flex likely won't do it for a VCS-only package).
  3. Create config/packages/data_watcher.yaml with at minimum from_email and recipients; set app_name so email subjects are readable.
  4. Configure a Messenger transport (sync is fine for smoke testing; async is what you actually want in production) and make sure the Scheduler consumes scheduler_default via a cron-driven messenger:consume worker.
  5. Run php bin/console debug:config data_watcher to see the actual resolved options, then php bin/console list data-watcher (or debug:container --tag) to discover the console commands and available tags the bundle exposes.

Look first at: the bundle's AbstractDoctrineCheck base class (that is the extension point called out in the README), the config tree under data_watcher, and the execution-history table the bundle creates. Those three things tell you almost everything about how to add a check, how to schedule it, and how to debug a run.

Your first use case should be deliberately small: one check that counts rows in a table over a window (e.g. "orders created in the last hour") and alerts if the count is zero or above a threshold. Get that through the scheduler, receive one email, confirm a row landed in execution history — then expand.

Implementation Patterns

Author one check per anomaly. Subclass AbstractDoctrineCheck, implement the query and threshold logic, and return a structured result the bundle can render into the email. Keep the query cheap and bounded: a COUNT(*) with a time filter against an indexed column is the sweet spot. Avoid loading entities into memory when a scalar query will do, and prefer DBAL SQL over DQL unless you genuinely need ORM hydration — the bundle works with doctrine/dbal alone, and doctrine/orm is only optional.

Separate detection from notification. The bundle's value proposition is that checks produce execution history and notifications as distinct concerns. Design checks to be pure-ish: given a connection and a time window, produce pass/fail + metrics. Let the bundle handle the mailer, templating, and history. That makes checks unit-testable without a mailer.

Schedule with the Scheduler, not ad-hoc cron. Register checks against symfony/scheduler and let it dispatch, with dragonmantank/cron-expression handling cron-style triggers. The practical workflow is: scheduler fires → message goes to Messenger → worker executes the check → history row written → mail sent. This decoupling is what keeps a slow check from blocking a request or a console run, and it gives you retries via Messenger.

Tune the transport per environment. In dev, use the sync:// transport (or Mailer's null:// + a log transport) so you can iterate quickly. In prod, use a real async transport for messenger:consume and a Mailer DSN you trust. Never let a dev environment point at the production recipient list.

Use the execution history as your observability layer. Every run should leave a record: which check, when, what result. Build your day-to-day debugging around querying that table — "did last night's check run?", "did it fail or just not fire?". Consider a small admin route or a console command that dumps the last N runs per check.

Group recipients by check, not globally. The global recipients list is a sane default for an early setup, but as you add checks, per-check recipient overrides (or multiple config profiles) prevent alert fatigue on low-priority checks and let finance own the revenue anomaly while you own the infrastructure ones.

Override Twig templates rather than forking. Notification templates live under Twig; Symfony's bundle template override convention (templates/bundles/DataWatcherBundle/...) lets you change subject lines, add run context, or link back to a dashboard without touching vendor code.

Treat thresholds as configuration, not code. Where the bundle allows per-check options, push numbers (expected minimums, percentage deltas, silence windows) into YAML or env vars. An anomaly threshold that requires a deploy to change will be wrong within a month.

Wire it into your existing alerting. Email is the built-in channel; if you already use Slack/PagerDuty, the cheapest integration is a check that posts to a webhook in addition to (or instead of) letting the bundle mail. Keep the bundle's detection and history, and treat email as one sink.

Gotchas and Tips

Adoption risk is real. Two stars and zero dependents means you are effectively an early adopter. Pin the exact version in composer.json, read the release notes for the last few tags before upgrading, and keep your checks in src/ under your own namespace so that if the bundle stalls you can reimplement the scheduler + mailer glue in an afternoon and keep the detection logic.

This is Symfony-only. The README's requirements are explicit about framework-bundle, messenger, mailer, twig-bundle, scheduler. Do not attempt to drop it into a Laravel app expecting service providers — you'd be porting the concepts, not the package.

Scheduler needs a running consumer. A common "it never emails" bug is that everything is configured but nothing is consuming the scheduler_default transport. Make sure a cron entry runs messenger:consume scheduler_default (or your scheduler transport name), and that messenger has that transport defined in config/packages/messenger.yaml. Also check the scheduler's own SCHEDULE setup — the scheduled tasks must be registered for the cron to do anything.

Cron expressions need dragonmantank/cron-expression. If it's missing, cron-based triggers will fail at runtime, not at compile time. Add it explicitly rather than assuming a transitive dependency covers it.

from_email and recipients are mandatory. Missing either produces a config exception at container compile time. app_name is optional but omitting it degrades email subjects; set it.

Doctrine DBAL major versions differ. ^3.0 and ^4.0 are both supported, but result APIs differ in places. If you write custom checks using executeQuery() and row fetching, verify behavior on your installed major — DBAL 4 removed several legacy fetch methods.

Watch the execution-history table's growth. Per-run rows accumulate forever unless you prune. Add a scheduled cleanup command (or a DB job) after a few weeks, and index the columns you actually query (check name, executed-at, status).

Anomaly checks are prone to timezone and window-boundary bugs. "Last 24 hours" computed from NOW() in the DB versus PHP-generated timestamps can disagree near midnight and around DST. Prefer computing windows in one place (the check) and pass explicit DateTimeImmutable bounds to the query rather than using database-relative time.

Alert on flapping, not just thresholds. A check that fails once at 03:00 and again at 03:05 will send two emails. Add a "consecutive failures before notify" or a cooldown in your check logic — the bundle gives you history, use it to suppress noise.

Test checks without the mailer. Instantiate your check classes directly in a unit test with a test connection (or a mocked Connection), assert on the returned result, and only exercise the full scheduler → message → mail path in one integration test. This isolates the parts most likely to break (queries, thresholds) from the parts that are slowest to run (mailer, scheduler).

Check the extension points before forking. The README calls out AbstractDoctrineCheck explicitly; look for tagged services, template namespaces, and config options for recipients/thresholds before patching vendor code. Given the low release cadence, a fork will be painful to maintain.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc