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

Laravel Actionable Diagnostics Laravel Package

alex-kassel/laravel-actionable-diagnostics

Laravel Actionable Diagnostics brings structured health checks to your app, surfacing issues in configuration, environment, and services with clear, actionable fixes. Catch problems early and resolve them faster with diagnostics that tell you exactly what to do next.

View on GitHub
Deep Wiki
Context7

Getting Started

This package gives you two things you wire up once and then lean on constantly: a diagnostic event engine that fans a single event out to multiple channels (webhooks among them), and an actionable exception framework so thrown exceptions carry enough context to be acted on rather than just logged.

Minimal path:

  1. composer require the package, then publish its config:
    php artisan vendor:publish --provider="...\ActionableDiagnosticsServiceProvider"
    
    (Check vendor/.../config/actionable-diagnostics.php for the exact publish tag.)
  2. Open config/actionable-diagnostics.php first — this is the package's whole contract. v1.0.2 standardized it at the top level, so read the channel list, webhook settings, and the routes block before writing any code.
  3. Leave actionable-diagnostics.routes.enabled off initially. You do not need the HTTP ingestion endpoint to get value; the outbound/webhook path and the exception framework work without it.
  4. First use case: throw one of the package's actionable exceptions (or dispatch a diagnostic event) from a real failure point — a queued job, a payment webhook handler — and confirm you receive the webhook payload. That end-to-end loop is the fastest way to understand the payload shape.

Where to look first, in order: config/actionable-diagnostics.php → the package README Quick Links (added in v1.0.3, points at the exception contract and channel docs) → WebhookDispatcher source, since that's where the actual HTTP behavior lives.

Implementation Patterns

Wrap, don't replace, your exception handler. The actionable exception framework is designed to sit inside Laravel's existing handler, not to be a second one. In bootstrap/app.php:

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->reportable(function (ActionableDiagnostic $e) {
        // context/actions travel with the exception itself
    });
})

Keep your normal report()/render() behavior; let actionable exceptions add structure on top.

Throw domain exceptions that carry their own remediation. The framework's point is that a PaymentDeclinedException knows what the operator should do. Encode that at the throw site (context array, suggested action, severity) rather than reconstructing it later in a log parser. This is the single highest-leverage habit with this package: the throw site is where diagnostics are cheap.

Treat the event engine as a fan-out, not a loop. Dispatch one diagnostic event; let the configured channels decide delivery. Resist the temptation to call the webhook dispatcher directly from business logic — that couples you to one channel and bypasses the engine's routing/severity rules. If you need a new destination, add it as a channel in config rather than sprinkling dispatch calls.

Webhooks in tests are now trivially fakeable. v1.0.2 refactored WebhookDispatcher onto Illuminate\Support\Facades\Http, which means:

Http::fake(['*' => Http::response([], 200)]);
// ... trigger the failure ...
Http::assertSent(fn ($request) => $request['severity'] === 'critical');

This is the biggest day-to-day quality-of-life change in this release. Assert on the payload content of your diagnostics, not just that an exception was reported — that's where regressions hide.

Gate the ingestion routes like an admin endpoint. When you do enable actionable-diagnostics.routes.enabled, set routes.prefix to something non-obvious and put auth middleware in front of it. These routes accept diagnostic inbound traffic; on a public host they are an abuse vector. Pattern: enable only on staging/worker hosts, or behind auth:sanctum + IP allowlist.

Queue the outbound side for anything user-facing. A synchronous webhook in a request cycle adds another service's latency to your own. Dispatch diagnostics from queued jobs/after-response where possible.

Gotchas and Tips

  • Routes are opt-in and disabled by default — and config caching will bite you. After flipping routes.enabled or prefix, run php artisan config:clear (or config:cache in a deploy step). A stale cached config is the most likely reason "the routes don't exist."
  • Http::preventStrayRequests() breaks the dispatcher in test suites. If your base TestCase blocks stray requests, the webhook channel will throw instead of silently no-op'ing. Either Http::fake() the diagnostic host in setUp(), or explicitly allow it.
  • Http facade refactor means real timeouts and retries are now yours. The dispatcher no longer hides its transport. Set explicit connect/read timeouts in config; a hung diagnostic endpoint should never hold a worker. Consider ->retry() semantics carefully — a retried diagnostic can duplicate alerts on the receiving side.
  • PHPStan Level MAX compliance is a signal, not a guarantee for your code. If you extend the package (custom channels, subclasses of the actionable exception), expect generic iterable annotations (array<int, Channel>, iterable<string, mixed>) to be enforced on your side too. Follow the package's array-shape conventions or you'll be fighting @phpstan-ignore lines.
  • .gitattributes export-ignore means the installed package has no tests. You can't read the package's own test suite from vendor/ to learn intended usage — read it on GitHub instead. This is a docs-navigation gotcha, not a bug.
  • Debugging delivery: the fastest loop is Http::fake() + Http::assertSent in a tinker/test, then Http::fake(fn () => Http::response()) to inspect the serialized payload. If a webhook "isn't arriving," verify the event was dispatched before suspecting the transport — channel misconfiguration in actionable-diagnostics.php silently drops events more often than HTTP fails.
  • Extension points: custom channel implementations and container bindings around the dispatcher are the supported seams. Prefer a custom channel over forking WebhookDispatcher; the transport was just standardized, and forks of it will drift.
  • Version hygiene: v1.0.0 → v1.0.3 is all additive within a single minor — no deprecations, no breaking changes. Safe to adopt at ^1.0. Note v1.0.3 is docs/packaging-only (README header, badges, release-gate file) and changes nothing at runtime.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib