Preskočiť na obsah
DevOps PHP 8. september 2026 · 12 min čítania

Monitoring PHP aplikácie: aby ste to zistili prví

Najhorší spôsob, ako sa dozvedieť o výpadku, je telefonát od klienta. Druhý najhorší je e-mail od zákazníka, ktorý tri dni nedostal potvrdenie objednávky. Základný monitoring, ktorý vás upozorní skôr než používatelia, sa dá postaviť za pol dňa a z veľkej časti z bezplatných nástrojov. Tento článok popisuje, čo sledovať a ako nastaviť upozornenia, ktoré sa dajú brať vážne.

DC

Dušan Chlpek

PHP vývojár, GEAR s.r.o. · 25+ rokov praxe

Štyri vrstvy, ktoré treba sledovať

Monitoring nie je jedna vec. Sú to štyri samostatné otázky, na ktoré potrebujete odpoveď:

  1. Beží to? — dostupnosť zvonku, z pohľadu používateľa.
  2. Funguje to správne? — chyby v aplikácii, ktoré stránku nezhodia, ale niečo pokazia.
  3. Funguje to na pozadí? — fronta, plánované úlohy, integrácie.
  4. 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:

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.

Health endpoint nesmie prezradiť detaily systému. Verzie, názvy serverov, chybové hlášky z výnimiek — to všetko je informácia pre útočníka. Vracajte len „ok" a „chyba", podrobnosti nechajte v logu.

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:

#!/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:

Minimum pre malý projekt: externá kontrola health endpointu, Sentry pre výnimky, denný ping z plánovanej úlohy a shellový skript na disk a zálohy. Pokryje to drvivú väčšinu reálnych problémov a nasadenie zaberie pol dňa.

Zhrnutie

Dozvedáte sa o problémoch od zákazníkov?

Nastavím monitoring vašej PHP aplikácie vrátane health endpointu, zberu výnimiek, kontroly fronty a záloh. Súčasťou je aj mesačná servisná starostlivosť, ak o ňu máte záujem.

Ďalšie články

Zavolať E-mail Dopyt

Ochrana súkromia

Táto stránka využíva cookies pre nevyhnutné fungovanie. Rešpektujeme vaše súkromie a legislatívu GDPR.