modulusphp/hibernate
ModulusPHP Hibernate is a lightweight Laravel package that lets you hibernate parts of your app—pausing models, features, or behavior instead of deleting them—so you can temporarily disable functionality and restore it later with minimal code changes.
What this package gives you. A Laravel logging integration layer that sits on top of Monolog: it registers log channels, wires them into config/logging.php, and ships first-class handlers (including Slack). The v1.9.3.4 release adds two things you will likely touch early:
Minimal steps.
composer require <vendor>/<package>
php artisan vendor:publish --provider="<Vendor>\<Package>\<PackageServiceProvider>"
config/logging.php (or use the package's own config file if it ships one) — start with a single daily/stack channel so you can confirm log flow before adding external transports..env:
LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T000/B000/XXXX
php artisan tinker
>>> logger()->channel('slack')->error('deploy smoke test');
First use case. Point your existing stack channel at Slack only for error and above, so alerting arrives without drowning a channel in debug noise. That is the highest-value, lowest-risk first integration.
Where to look first. config/logging.php for channel wiring, the package's own config for driver registration and Slack options, and the package's ServiceProvider to see how drivers are resolved (this is also the extension point for the new custom-driver feature).
Pattern 1 — Slack alerting for production errors. Keep the default stack channel for file logs, and add Slack as a nested channel with a level floor:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
],
'slack' => [
'driver' => 'slack',
// v1.9.3.4+: webhook-only configuration
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => env('LOG_SLACK_LEVEL', 'error'),
],
],
Using stack here means a single Log::error() fans out to disk and Slack — no channel juggling in application code.
Pattern 2 — Webhook for simple alerts, token for interactive bots. The new webhook path is ideal for one-way alerting (CI failures, queue worker deaths, 500s). Retain token-based auth where you need the Slack Web App API surface — e.g. posting to a specific thread, reacting, or looking up users. Treat the two as separate channels if you need both.
Pattern 3 — Registering a custom Monolog driver. The custom-driver feature is the release's most extensible addition. The usual shape:
// config/logging.php
'channels' => [
'datadog' => [
'driver' => 'monolog',
'handler' => \App\Logging\DatadogHandler::class,
'with' => ['apiKey' => env('DD_API_KEY')],
],
],
Or, if the package exposes a registration hook in its service provider / config map, register a driver name that resolves to your factory:
// AppServiceProvider::boot()
Log::extend('datadog', function (array $config) {
return (new Logger('datadog'))->pushHandler(
new \App\Logging\DatadogHandler($config['api_key'])
);
});
Wrap third-party handlers in a small adapter that implements Monolog\Handler\HandlerInterface and normalises LogRecord vs. legacy array records — Monolog 2/3 differences are the most common source of breakage here.
Pattern 4 — Per-environment channels. Keep Slack quiet locally and loud in staging/production. Prefer a LOG_SLACK_ENABLED-style flag read at config-build time over if (app()->environment()) inside handlers; it keeps config declarative and testable.
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'level' => app()->environment('production') ? 'error' : 'emergency',
],
Pattern 5 — Contextual enrichment. Slack messages are far more useful with request/user context. Attach via a Monolog processor rather than in each call site:
Log::channel('slack')->withContext([
'user_id' => auth()->id(),
'request_id' => request()->header('X-Request-Id'),
])->error($e->getMessage());
Pattern 6 — Feature/queue integration. Use Slack channels for failed job events and scheduled-task failures. A single failed channel referenced by queue.failed config (logging.failed in config/queue.php) turns silent worker deaths into visible alerts.
Pattern 7 — Testability. In tests, swap the channel for a fake or use Log::spy()/Log::shouldReceive() so you assert on the log call rather than hitting Slack. Never let a test suite depend on a webhook URL.
Webhook vs. token is not a drop-in swap. If you migrate existing Slack config to webhooks, delete the old token keys entirely. Leaving both a token and a url present leads to ambiguous resolution — behaviour depends on package version and is easy to misdiagnose. Pick one channel definition per destination.
Webhook URLs are secrets. They grant post access to the channel. Keep them in .env/secrets manager, never in committed config, and rotate immediately if a URL leaks into logs or a repo. Note that webhook URLs also carry the channel target — you cannot retarget a message to another channel at runtime without a different URL (or token auth).
Rate limits. Slack enforces per-webhook rate limits and will return HTTP 429 with a Retry-After. Under an error storm, a naive Slack channel amplifies your problem: every exception is a network call, and a slow/failing webhook can stall request handling. Mitigations: WhatFailureGroupHandler, a FingersCrossedHandler, an async/queue-backed handler, or a buffer handler that flushes at request end.
Never let logging throw. A logging failure should never turn a 200 into a 500. Wrap the Slack handler in a failure-tolerant group and log a local warning instead.
Custom drivers: resolution order matters. When registering a custom driver, confirm whether the package resolves drivers by (a) driver key matching a registered name, or (b) a handler class reference. Mixing them usually yields InvalidArgumentException: Driver [...] is not supported. Check the package's channel factory/service provider first, then the Laravel Log::extend fallback.
Handler constructor signatures differ between Monolog majors. If your custom driver instantiates via 'with' => [...] named args, a Monolog major bump can silently break the mapping. Pin Monolog in composer.json or add a test that instantiates every custom channel — php artisan config:cache succeeding does not validate driver construction; the failure surfaces on first write.
Config caching hides env changes. After editing channel/Slack config, run php artisan config:clear (or re-cache). A stale bootstrap/cache/config.php is the #1 cause of "I set the webhook but it still posts to the old one."
Level thresholds are inclusive. 'level' => 'error' captures error, critical, alert, emergency — not warning. If you expected warnings in Slack, you set it wrong; conversely, 'debug' on a busy app will get you rate-limited fast.
Debugging checklist for a silent Slack channel: (1) config('logging.channels.slack') is populated post-cache; (2) the channel is actually in the stack list; (3) the log level passes the floor; (4) the handler isn't swallowing exceptions in a failure group; (5) the webhook responds to a manual curl -X POST -d '{"text":"test"}'. Isolate at each step rather than blaming the package.
Extension points worth knowing. The channel factory / Log::extend registration is the sanctioned hook for custom drivers; a Monolog processor is the right place for shared context; a formatter is the right place for Slack message shape (blocks, attachments) if the package exposes it. Avoid subclassing the package's channel class — it is version-fragile.
Pin and read the changelog. This release is additive (no deprecations flagged), so an upgrade from 1.9.x should be low-risk. Still pin ^1.9 and skim release notes for handler-signature changes before bumping minor versions in production.
How can I help you explore Laravel packages today?