Štyri vrstvy, ktoré treba sledovať
Monitoring nie je jedna vec. Sú to štyri samostatné otázky, na ktoré potrebujete odpoveď:
- Beží to? — dostupnosť zvonku, z pohľadu používateľa.
- Funguje to správne? — chyby v aplikácii, ktoré stránku nezhodia, ale niečo pokazia.
- Funguje to na pozadí? — fronta, plánované úlohy, integrácie.
- Vydrží to? — miesto na disku, pamäť, expirácia certifikátov, rast databázy.
Väčšina projektov má pokrytú len prvú vrstvu — a práve v druhej a tretej vzniká najviac škody, lebo tie zlyhávajú potichu.
Vrstva 1: dostupnosť zvonku
Externá kontrola musí bežať mimo vášho servera. Monitoring, ktorý beží na tom istom stroji ako aplikácia, o jeho výpadku neinformuje.
Použiteľných je viacero bezplatných služieb, prípadne si viete nasadiť vlastný nástroj typu Uptime Kuma na malom VPS inde. Podstatné je nastavenie:
- Kontrolujte URL, ktorá naozaj niečo robí — nie statickú úvodnú stránku zo cache. Ideálne health endpoint (viď nižšie).
- Interval 1 až 5 minút podľa dôležitosti projektu.
- Upozornenie až po dvoch neúspešných kontrolách za sebou — jedna vynechaná odpoveď je často len sieťový výkyv.
- Sledujte aj platnosť certifikátu a expiráciu domény. Výpadok kvôli neobnovenému certifikátu je zbytočný a pravidelný.
Health endpoint, ktorý hovorí pravdu
Endpoint vracajúci natvrdo „OK" je na nič. Zmysel má vtedy, keď overí, že aplikácia sa vie dostať k svojim závislostiam:
Route::get('/health', function () {
$kontroly = [];
try {
DB::connection()->getPdo()->query('SELECT 1');
$kontroly['databaza'] = 'ok';
} catch (Throwable) {
$kontroly['databaza'] = 'chyba';
}
try {
Cache::store('redis')->put('health', now()->timestamp, 10);
$kontroly['cache'] = Cache::store('redis')->has('health') ? 'ok' : 'chyba';
} catch (Throwable) {
$kontroly['cache'] = 'chyba';
}
$volneMB = (int) (disk_free_space(base_path()) / 1024 / 1024);
$kontroly['disk'] = $volneMB > 500 ? 'ok' : 'chyba';
$vsetkoOk = ! in_array('chyba', $kontroly, strict: true);
return response()->json(
['stav' => $vsetkoOk ? 'ok' : 'chyba', 'kontroly' => $kontroly],
$vsetkoOk ? 200 : 503,
);
});
Dôležitý je návratový kód 503 pri probléme — podľa neho sa riadi monitoring aj prípadný load balancer.
Vrstva 2: chyby v aplikácii
Chyba zapísaná do súboru, ktorý nikto nečíta, je z praktického hľadiska nezaznamenaná. Potrebujete nástroj, ktorý výnimky zbiera, zoskupuje a upozorní na nové.
Pre PHP je najbežnejšou voľbou Sentry, ktorý má použiteľnú bezplatnú úroveň a oficiálnu integráciu pre Laravel:
composer require sentry/sentry-laravel
php artisan sentry:publish --dsn=vaše-dsn
# .env
SENTRY_LARAVEL_DSN=https://...
SENTRY_TRACES_SAMPLE_RATE=0.1 # 10 % požiadaviek aj s meraním výkonu
Prínos oproti obyčajnému logu je zoskupovanie. Tisíc výskytov tej istej chyby je jedna položka s počítadlom, nie tisíc riadkov. Uvidíte, kedy sa chyba objavila prvýkrát, ktorá verzia ju priniesla a koľkých používateľov zasiahla.
Kontext, ktorý ušetrí hodiny hľadania
// app/Providers/AppServiceProvider.php
public function boot(): void
{
if (app()->bound('sentry')) {
\Sentry\configureScope(function (\Sentry\State\Scope $rozsah): void {
$rozsah->setTag('verzia', config('app.version'));
});
}
}
Pri zachytení výnimky pridajte údaje, ktoré vám umožnia problém zreprodukovať — identifikátor objednávky, názov integrácie, vstupné parametre. Nikdy však heslá, tokeny ani čísla kariet.
Štruktúrované logy
Voľný text sa zle prehľadáva. Ak logujete v JSON formáte s dôsledne pomenovanými kľúčmi, viete sa neskôr pýtať zmysluplné otázky:
// config/logging.php
'channels' => [
'integracie' => [
'driver' => 'daily',
'path' => storage_path('logs/integracie.log'),
'formatter' => Monolog\Formatter\JsonFormatter::class,
'days' => 30,
'level' => 'info',
],
],
Log::channel('integracie')->info('prenos_faktury', [
'objednavka_id' => $objednavka->id,
'system' => 'uctovnictvo',
'trvanie_ms' => $trvanie,
'vysledok' => 'ok',
]);
Oddelené kanály pre jednotlivé oblasti (integrácie, platby, bezpečnosť) sa vyplatia okamžite. Hľadanie jedného prenosu v spoločnom logu so všetkým ostatným je zbytočná práca.
Vrstva 3: procesy na pozadí
Toto je najčastejšie prehliadaná oblasť. Worker fronty spadne, supervisor ho nereštartuje a e-maily sa tri dni neodosielajú — pritom web beží a monitoring hlási zelenú.
Sledujte dĺžku fronty a najstaršiu úlohu
class KontrolaFronty extends Command
{
protected $signature = 'kontrola:fronta';
public function handle(): int
{
$cakajuce = Queue::size('default');
$zlyhane = DB::table('failed_jobs')
->where('failed_at', '>=', now()->subHour())
->count();
if ($cakajuce > 500) {
$this->upozorni("Fronta má {$cakajuce} čakajúcich úloh.");
}
if ($zlyhane > 10) {
$this->upozorni("Za poslednú hodinu zlyhalo {$zlyhane} úloh.");
}
return self::SUCCESS;
}
}
Rastúca fronta je najskorší príznak problému — spravidla sa objaví skôr než chybové hlášky. Viac o správnom nastavení fronty a workerov píšem v článku o Laravel Queues a Jobs.
Overujte, že plánované úlohy naozaj bežali
Plánovač vyžaduje bežiacu položku v cron tabuľke. Ak ju niekto pri migrácii servera zabudne preniesť, nič sa nestane — presnejšie, nestane sa vôbec nič a nikto si to nevšimne. Riešením je princíp „mŕtveho muža": úloha po úspešnom dobehnutí zavolá externú službu. Keď volanie nepríde, služba upozorní vás:
// routes/console.php
Schedule::command('reporty:denny')
->dailyAt('06:00')
->onSuccess(function () {
Http::get(config('monitoring.ping_denny_report'));
})
->emailOutputOnFailure(config('monitoring.admin_email'));
Bezplatne to pokryje napríklad Healthchecks.io alebo vlastná jednoduchá služba. Princíp je podstatnejší než konkrétny nástroj: kontrolujete, že sa niečo stalo, nie že nenastala chyba.
Vrstva 4: zdroje servera
Na jednom serveri s jednou aplikáciou nepotrebujete Prometheus a Grafanu. Stačí denná kontrola a upozornenie pri prekročení hranice:
- Miesto na disku — najčastejšia príčina nočného výpadku. Vinníkom bývajú logy a zálohy, ktoré nikto nemaže.
- Pamäť a swap — aktívne swapovanie znamená, že aplikácia je pomalá bez zjavnej príčiny.
- Veľkosť databázy a rast najväčších tabuliek.
- Platnosť SSL certifikátu — automatické obnovenie cez Let's Encrypt a kontrola, že naozaj prebehlo.
- Zálohy — existuje záloha z dnešnej noci a má očakávanú veľkosť? Nulová veľkosť zálohy je horšia než žiadna, lebo vytvára falošný pocit istoty.
#!/bin/bash
# /usr/local/bin/kontrola-servera.sh — spúšťať denne cez cron
PRAH=85
POUZITE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$POUZITE" -gt "$PRAH" ]; then
echo "Disk je zaplnený na ${POUZITE} %." | \
mail -s "[VAROVANIE] Miesto na disku" admin@firma.sk
fi
ZALOHA=$(find /var/backups -name "*.sql.gz" -mtime -1 | head -1)
if [ -z "$ZALOHA" ]; then
echo "Za posledných 24 hodín nevznikla žiadna záloha." | \
mail -s "[KRITICKÉ] Chýba záloha" admin@firma.sk
fi
Alerty, ktoré sa dajú brať vážne
Monitoring zlyháva najčastejšie nie technicky, ale ľudsky: posiela toľko upozornení, že ich prestanete čítať. Pravidlá, ktoré tomu bránia:
- Upozornenie musí znamenať akciu. Ak na správu nikdy nereagujete, nemá tam čo robiť — zrušte ju alebo zvýšte prah.
- Rozlišujte naliehavosť. Web nedostupný = telefón okamžite. Fronta rastie = správa v pracovnom čase. Disk na 85 % = denný súhrn.
- Zoskupujte. Sto rovnakých chýb za minútu je jedno upozornenie s počtom, nie sto správ.
- Pošlite aj správu o obnovení. Bez nej neviete, či problém pominul.
- Raz za štvrťrok skontrolujte, že monitoring funguje. Vypnite na chvíľu testovaciu službu a overte, že vám prišlo upozornenie. Tichý monitoring môže znamenať pokoj aj to, že už mesiac nič nekontroluje.
Zhrnutie
- Externá kontrola dostupnosti musí bežať mimo monitorovaného servera
- Health endpoint overuje databázu, cache a disk a vracia 503 pri probléme
- Výnimky zbierajte do nástroja, ktorý ich zoskupuje — nie do súboru, ktorý nikto nečíta
- Logujte štruktúrovane a v oddelených kanáloch podľa oblasti
- Sledujte dĺžku fronty a počet zlyhaných úloh
- Plánované úlohy kontrolujte princípom „mŕtveho muža" — hlásia úspech, nie chybu
- Disk, zálohy a platnosť certifikátu kontrolujte denne
- Každé upozornenie musí viesť k akcii, inak ho zrušte
- Funkčnosť monitoringu si raz za štvrťrok overte v praxi