Mikor bukik el csendben egy Laravel alkalmazás
Egy Laravel app gyakran ott esik el, ahol senki nem figyel: a queue worker megakadt, a scheduler nem fut, a Redis kapcsolat megszakadt, a Horizon process leállt, vagy a deploy után elfelejtődött a php artisan config:cache. A webes felület közben hibátlanul fut, a látogató mindenből 200-at kap, csak épp a háttérben senki nem küldi ki az emaileket és senki nem dolgozza fel a beérkező webhookokat.
Ez a tutorial végigvezet azon, mit érdemes pontosan figyelni egy Laravel projektnél, hogyan állíts össze egy saját /health végpontot, és hogyan állítsd be ezeket az uptimes.hu admin felületén. A végén kapsz egy konkrét monitor portfóliót, ami egy átlagos Laravel projekthez 5-6 monitorból elég.
Mit érdemes monitorozni egy Laravel alkalmazásban?
Egy production Laravel app öt különböző helyen tud "csendben" elesni:
- A nyilvános HTTP réteg (Nginx + PHP-FPM, vagy Laravel Octane).
- Az adatbázis (MySQL, PostgreSQL): a
DB::selecthibára 500-ast dob, de connection pool exhaustion gyakran csak lassuláshoz vezet. - A cache és session store (Redis, Memcached): Redis kiesésnél az
authés sok queue is megakad. - A queue worker és Horizon: ha nem fut, akkor az emailek, a Stripe webhookok feldolgozása és a háttérfeladatok elnémulnak.
- A scheduler: ha a cron
* * * * * php artisan schedule:runnem fut a szerveren, akkor a napi riportok, takarítás, sitemap generálás kimaradnak.
Mindegyikre máshogy érdemes figyelni. A frontendet egy egyszerű HTTPS check fedi le, a többit egy saját /health JSON végpont és néhány tudatos artisan parancs.
1. Frontend HTTPS elérhetőség beállítása
Ez az alap uptime ellenőrzés. Az oldalad nyilvános URL-jét hívja percenként, és nézi, hogy 200-ast kap-e.
Lépések:
- Monitors menü, + Új monitor, HTTP(S) csempe.
- Töltsd ki a mezőket:
| Mező | Érték |
|---|---|
| Monitor name | Laravel frontend |
| URL | https://az-appod.hu/ |
| HTTP method | GET |
| Expected status codes | 200, 301, 302 |
| Follow redirects | be |
| Timeout | 15 mp |
| Response keyword | </html> |
A </html> egy biztonságos záró tag, ami minden Blade-renderelt válaszban szerepel. Ha a Laravel "Whoops" error oldalt szolgál ki (debug módban), vagy egy üres 500-as választ, akkor ez a tag eltűnik, és a monitor DOWN-ot jelez akkor is, ha a status code 200.
Production-ben APP_DEBUG=false-ra állítva a Laravel egy egyedi error page-et szolgál ki 500-as kóddal, így a status code önmagában is megfogja a hibát. De a </html> keyword check egy extra védelmi vonal.
2. Saját /health endpoint Laravel-ben
A legjobb gyakorlat egy dedikált /health route, ami JSON-ben válaszol vissza a kritikus függőségek állapotáról. Ezt percenként pinglet az uptimes.hu, és JSON field check-kel pontos hibadetektálást kapsz.
Hozd létre a route-ot a routes/web.php vagy routes/api.php fájlban:
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Queue;
Route::get('/health', function () {
$checks = [
'db' => false,
'cache' => false,
'queue' => false,
];
try {
DB::select('SELECT 1');
$checks['db'] = true;
} catch (\Throwable $e) {
// log if needed
}
try {
Cache::put('health_ping', '1', 10);
$checks['cache'] = Cache::get('health_ping') === '1';
} catch (\Throwable $e) {
//
}
try {
// Queue size jelez, hogy a redis/db queue elérhető
Queue::size();
$checks['queue'] = true;
} catch (\Throwable $e) {
//
}
$allOk = !in_array(false, $checks, true);
return response()->json([
'status' => $allOk ? 'ok' : 'error',
'db' => $checks['db'] ? 'up' : 'down',
'cache' => $checks['cache'] ? 'up' : 'down',
'queue' => $checks['queue'] ? 'up' : 'down',
'time' => now()->toIso8601String(),
], $allOk ? 200 : 503);
})->name('health');
Új monitor:
| Mező | Érték |
|---|---|
| Monitor name | Laravel health endpoint |
| URL | https://az-appod.hu/health |
| HTTP method | GET |
| Expected status codes | 200 |
| Timeout | 10 mp |
Response keyword check (free csomag): "status":"ok".
JSON field check (Starter csomagtól, pontosabb):
| Path | Expected |
|---|---|
status |
ok |
db |
up |
cache |
up |
queue |
up |
Ezzel ha bármelyik függőség elesik, a monitor azonnal DOWN-ot jelez, és látod a riasztásból, hogy melyik komponens a hibás (DB, cache, vagy queue).
Vigyázz az auth middleware-rel
A /health route-ot NE tedd auth middleware mögé. Ha véletlenül auth kell hozzá, akkor 401/302-t kapsz, és a monitor mindig DOWN-ot fog jelezni. Ha biztonsági okból nem szeretnéd publikusan elérhetővé tenni, akkor használj egy hosszú, kitalálhatatlan slug-ot (pl. /health/8f2a-b91c-internal), vagy egy egyedi headert (de a header support csomagfüggő).
3. Queue worker és Horizon figyelése
A Laravel queue worker két okból eshet el:
- A
php artisan queue:workprocess meghalt (supervisord nem indította újra), vagy - Maga a worker fut, de a queue connection (Redis, SQS, DB) elérhetetlen.
A 2. pontos /health végpont a Queue::size() hívással a 2. esetet detektálja. Az 1. esetre két opció van:
A. Supervisord status webhook: ha supervisord-t használsz, állíts be egy egyszerű script-et, ami egy webhook URL-re POST-ol, amikor a worker process leáll.
B. Heartbeat job: csinálj egy Laravel job-ot, ami minden percben fut és érint egy fájlt vagy egy Redis kulcsot egy timestamp-pel. A /health végpont olvassa ki ezt, és ha 90 másodpercnél régebbi, akkor DOWN-ot jelez.
// app/Jobs/HealthHeartbeat.php
public function handle(): void
{
Cache::put('worker_heartbeat', now()->timestamp, 300);
}
Schedule-old percenként:
// app/Console/Kernel.php
$schedule->job(new \App\Jobs\HealthHeartbeat)->everyMinute();
A /health route-ban:
$lastHeartbeat = Cache::get('worker_heartbeat', 0);
$checks['worker'] = (now()->timestamp - $lastHeartbeat) < 90;
Add hozzá a JSON field check-hez: worker = up.
Horizon dashboard külön monitor
Ha Horizon-t használsz, akkor a /horizon dashboard maga is egy uptime indikátor. Egy külön monitor a /horizon-ra (auth-mentes status endpoint-tal, pl. /horizon/api/stats ha publikus) megerősítést ad.
4. Scheduler (cron) figyelés
A Laravel scheduler csak akkor fut, ha a szerveren a következő cron job aktív:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Ha a deploy felülírja a cron-t, vagy a szerver migrálásakor elveszik, akkor a napi riportok, sitemap újragenerálás, takarítások megszűnnek, de látható hibajel nincs.
A 3. pontban már bevezetett heartbeat job ezt is lefedi: ha a worker_heartbeat cache kulcsot a scheduler indítja (és nem a queue worker), akkor a scheduler kiesése a /health válaszban azonnal látszik.
Másik lehetőség az Spatie Schedule Monitor package: ez minden ütemezett feladatról logot vezet és ping URL-eket küld. Kombinálható az uptimes.hu webhook funkcióval.
5. SSL tanúsítvány automatikus figyelése
Minden HTTPS monitor mellé az uptimes.hu automatikusan figyeli a tanúsítvány lejáratát. Külön monitort nem kell beállítani. A figyelmeztetés 30, 14, 7 és 1 nappal a lejárat előtt érkezik.
Laravel Forge és Vapor felhasználóknak: a Let's Encrypt megújítás automatikus, de néha eltörik (pl. ha a domain DNS rekord megváltozott). A 30 napos figyelmeztetés bőven elég idő a manuális beavatkozásra.
6. Értesítések beállítása (Slack, Discord, email)
Minden monitornál választható csatorna. Ajánlott szétosztás:
- Email: a fiók email-edre, "log" funkció.
- Slack
#alerts-prod: minden produkciós monitor. - Slack
#alerts-internal: a queue/scheduler health (nem ügyfélnek látható, de fontos). - Webhook: ha PagerDuty / Opsgenie van használatban.
A monitor szerkesztőben + Create new channel linkkel hozhatsz létre újat. Mentés után visszadob a monitor szerkesztésére.
Laravel-specifikus buktatók
Queue stuck állapot (job nem futott le, de nincs hiba)
Ha egy job végtelen ciklusba vagy hosszú külső API hívásba ragad, akkor a Queue::size() nem nullázódik, és a worker látszólag fut. Erre két megoldás van:
- Timeout a job-on:
$timeout = 60;minden Job classban, így ha 60 mp-en túl tart, a worker leöli és újraindítja. - Queue size alert: ha a
Queue::size()5 perce nagyobb mint 100, az is jelez. Ezt a/healthválaszba bele tudod tenni egy extraqueue_sizemezőként, és külön monitort csinálsz csak erre a JSON path-ra.
Telescope feltölti a diszket
Production-ben sokan elfelejtik a Telescope-ot kikapcsolni vagy pruning-olni. A telescope_entries tábla néhány hét alatt több GB-os méretre nő, és lemerítheti a diszket. Ezt nem az uptimes.hu fogja megoldani, de:
- A
/healthroute-ban kiolvashatod adisk_free_space('/')értéket, és ha 1 GB alatt van, akkordisk=lowa JSON-ben. - Adj hozzá egy JSON field check-et:
disk=ok.
Forge deploy után config cache
Ha a deploy után elfelejtődik a php artisan config:cache, akkor a régi .env értékek élnek. Ez nem mindig okoz 500-ast, csak rossz konfigurációval futnak a kérések (pl. régi DB connection, régi Stripe kulcs). A 2. pontos /health végpontba tehetsz egy ellenőrzést: olvasd ki a config('app.deploy_hash') értéket, és nézd meg, hogy egyezik-e a git commit hash-sel.
$checks['config_fresh'] = config('app.deploy_hash') === env('DEPLOY_HASH');
Ehhez a deploy lépésben .env-be be kell írni a commit hash-t.
Cloudflare és WAF false-DOWN
Ha Cloudflare-t használsz "Under Attack Mode"-ban, a monitor 503-as challenge oldalt kaphat. Két megoldás:
- Vedd fel az 503-at az expected status codes-ba (de ekkor valódi overload sem fog jelezni).
- Whitelist-eld az uptimes ellenőrző tartományokat a Cloudflare WAF-jában.
A 2. opció a tisztább, mert a monitor a valódi Laravel választ fogja vizsgálni.
Ajánlott monitor portfólió Laravel alkalmazáshoz
| # | Monitor | URL | Interval | Check |
|---|---|---|---|---|
| 1 | Frontend | https://az-appod.hu/ |
1 perc | keyword: </html> |
| 2 | Health endpoint | https://az-appod.hu/health |
1 perc | JSON: status=ok, db=up, cache=up, queue=up, worker=up |
| 3 | Login flow | https://az-appod.hu/login |
5 perc | keyword: name="email" |
| 4 | Kritikus API endpoint | https://az-appod.hu/api/v1/orders |
5 perc | expected: 401 (auth-protected, de él) |
| 5 | Horizon dashboard | https://az-appod.hu/horizon |
5 perc | expected: 200, 302 |
A 4. egy trükk: egy auth mögötti API endpoint-ra 401-et várunk, mert ez bizonyítja, hogy a route létezik és a middleware fut. Ha a route 404-et adna, akkor a deploy közben elveszett valami.
Az SSL lejáratot az 1. és 2. monitor mellett automatikusan figyeli a rendszer.
Próbáld ki ingyen
Az ingyenes csomaggal 5 monitort tudsz futtatni 5 perces intervallumon, ami pont elég egy Laravel app teljes lefedéséhez. SSL figyelés, email értesítés, 7 napos history alapból benne van.
Ha JSON field check-et akarsz használni (az ajánlott /health flow miatt erősen javasolt), a Starter csomag 2990 Ft / hó. Egyetlen kiesés-mentes éjszaka megéri.
Regisztrálj ingyen, és állítsd be az első Laravel monitort 5 perc alatt. Bankkártya nem kell az induláshoz.