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 Log Alarm Laravel Package

saasscaleup/laravel-log-alarm

Log Alarm monitors your Laravel application's logs in real time, detects error events, and instantly notifies you via Slack and email. Frequency thresholds and cache-based tracking prevent alert flooding, keeping your team informed without the noise.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish (5 minutes):

composer require saasscaleup/laravel-log-alarm
php artisan vendor:publish --provider="Saasscaleup\LogAlarm\LogAlarmServiceProvider"

On Laravel < 5.5 you also register Saasscaleup\LogAlarm\LogAlarmServiceProvider::class in config/app.php. On anything modern, package discovery handles it — confirm php artisan about or config/log-alarm.php exists after publishing and then stop thinking about the provider.

The first place to look is config/log-alarm.php, not the README. Every behavior is that one file. Read it top to bottom before touching .env, because the defaults (error, 5 errors per 1 minute, 5-minute cooldown) are aggressive enough to page you on a single flaky endpoint.

Minimum viable .env for a first smoke test — pick one channel, don't wire all four:

LA_ENABLED=true
LA_LOG_TYPE=error
LA_LOG_TIME_FRAME=1
LA_LOG_PER_TIME_FRAME=5
LA_DELAY_BETWEEN_ALARMS=5
LA_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...

Then prove the wire end-to-end:

php artisan tinker
>>> collect(range(1,5))->each(fn() => \Log::error('Log alarm'));

Five error lines inside a minute → one Slack message. If that doesn't fire, the problem is almost always the cache driver (see Gotchas) or config:cache serving a stale config, not the package.

First real use case: don't deploy this as a general error firehose on day one. Point it at one known-noisy-but-meaningful failure — a payment gateway timeout, a SQLSTATE burst, a queue worker dying — by setting LA_SPECIFIC_STRING. That gives you a single, high-signal alert channel your team learns to trust before you widen it.

Implementation Patterns

Treat thresholds as an on-call policy file, not a dev toggle. LA_LOG_PER_TIME_FRAME / LA_LOG_TIME_FRAME / LA_DELAY_BETWEEN_ALARMS decide whether your team gets paged. Put them in .env.example with comments, review changes like code, and keep a short decision note in the repo. The failure mode isn't "alerts don't work," it's "alerts got muted by someone debugging and nobody noticed."

Tier the config per environment. Typical shape:

Env LA_ENABLED LA_LOG_PER_TIME_FRAME LA_DELAY_BETWEEN_ALARMS Channels
local false — — none
staging true 1 1 Slack only
production true 5 15 Slack + email (+ Telegram)

Staging with a hair-trigger is the cheapest way to validate your specific_string and message formatting against real traffic without waking anyone.

Fan out by urgency, not by preference. Slack (LA_SLACK_WEBHOOK_URL) as the team channel, LA_NOTIFICATION_EMAIL as the durable record/to-address list ([email protected],[email protected] — it's a comma-separated string, not an array), Telegram for whoever is holding the phone, Discord if that's where the team already lives (v1.0.3). Configure only what you'll actually read; a channel nobody watches is just noise you pay for.

Narrow the signal with specific_string. Empty string means "any message." Set it to a distinctive fragment:

LA_SPECIFIC_STRING="Allowed memory size"
LA_LOG_TYPE=error,critical

The README advertises comma-separated log types (error,warning,debug) — verify the parsing in src/ before relying on it in production, since the config comment and the implementation don't always agree.

Log deliberately at failure boundaries. This package watches Laravel's log event pipeline, so the quality of its alerts is exactly the quality of your Log:: calls. Wrap third-party calls in try/catch and log with context so the alarm carries meaning:

try {
    $gateway->charge($order);
} catch (GatewayException $e) {
    Log::error('Payment gateway failure: '.$e->getMessage(), ['order_id' => $order->id]);
    throw $e;
}

Since v1.0.5 the notification includes LOG_FILE and LOG_LINE — but only when the log entry actually carries exception context. A bare Log::error('Log alarm') won't have them, so don't build a debugging workflow around that field until you've confirmed it on a real exception.

Keep it beside your APM, not instead of it. This is a threshold pager, not an observability tool: no traces, no grouping, no escalation, no cross-service aggregation. If you already run Sentry, use this as the "the whole app is on fire" backstop that works even when the SDK is down.

Test harness: set LA_ENABLED=false in phpunit.xml (or the testing env block of config/log-alarm.php) so a test that intentionally logs an error doesn't try to POST to Slack. If the package sends mail through the Mail facade, Mail::fake() assertions work for a dedicated alarm test — otherwise keep it out of your suite entirely and verify in Tinker instead.

Gotchas and Tips

The cache driver is the whole system. Counters and the cooldown lock live in cache, not a database. With the file driver on three app servers you have three independent counter sets — a threshold of 5 may never trip because errors distribute 2/2/1. Use Redis/Memcached/database cache in any multi-node deployment, or accept that the alarm is per-node.

Shared Redis means shared keys. Multiple apps on one Redis instance can collide. Set a distinct CACHE_PREFIX per app or the counters and the v1.0.7 lock will confuse each other.

php artisan cache:clear silently resets your alerting. The counters and the delay_between_alarms lock both live there. A deploy script that flushes cache every release means the cooldown evaporates and every deploy is a fresh window for duplicate pages.

The cooldown is a blunt instrument. LA_DELAY_BETWEEN_ALARMS is designed to prevent flooding, which means a burst of error A can suppress the notification for a completely unrelated, more serious error B arriving during the same window. Size the cooldown to your worst realistic error volume, not your best.

Alerting appears to group by message. The sample email reads "The Error was occurred 5 times… LOG_MESSAGE: …", implying per-message counting. If so, five different errors logged once each will never trip the threshold — which is fine for a storm but invisible for scattered one-offs. Confirm this in the source before you assume broad coverage.

config:cache in production is mandatory after env changes. The config file reads env() at load time; if you use cached config, editing .env does nothing until you re-run php artisan config:cache. This is the #1 "I set the webhook and nothing happened" cause.

Notification sending is in-process. The Slack POST / SMTP send happens on the request that logged the error. A slow or unresponsive SMTP host adds latency to a request that is already failing. Prefer a fast transactional mail provider, and know that a webhook timing out doesn't retry — the alarm is simply lost.

Delete the published migration. vendor:publish emits a migration the package doesn't use (cache-based by design). Shipping a table you never read is a question in every code review; publish config only, or delete the migration immediately.

Container/stderr logging can break everything. If your production stack logs to stderr (Docker, Lambda, Herrera) or uses a custom Monolog formatter, the message string that reaches the listener may differ from what you tested locally — specific_string matching quietly stops working. Validate against the production log stack, not Sail.

Pin the version. The package is actively moving (Discord, Telegram, file/line, cache locking all landed within a few releases). composer require "saasscaleup/laravel-log-alarm:^1.0" and read the changelog before bumping; a lock-mechanism change alters alert semantics, not just internals.

Extension path is a PR, not a plugin. There's no documented driver interface for custom channels — Discord and Telegram arrived as community pull requests. If you need Teams or PagerDuty, budget for a fork or an upstream PR, and keep the fork small since the surface area is one listener plus a handful of notification methods.

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.
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator
manelgavalda/enrollment_mobile
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics