U hodně navštěvovaných aplikací je k nezaplacení mít čítače na jednotlivé akce, např. zobrazení článku, vložení komentáře, provedené vyhledávání, ale třeba i ty nízkoúrovňovější jako počet zavolání nějaké funkce, počet konfliktů unikátního klíče v databázi nebo třeba celkový čas sestavení stránky. Vlastně se to hodí u všech aplikací, nejen u těch hodně navštěvovaných.
Monitorováním těchto čítačů (a např. automatickým posláním upozornění při jejich náhlé změně) můžeme rychle zjistit, že je něco v nepořádku. Navíc můžeme sledovat vliv změn, které v aplikaci provádíme, např.: „Mělo přesunutí tlačítka pro vložení komentáře vliv na počet nových komentářů?“
Logování těchto akcí ale samozřejmě jako každý zápis něco stojí, takže se jím často šetří. Jak logování nastavit tak, aby bylo co nejrychlejší? Potřebujeme lokální paměťové úložiště, které přežije ukončení skriptu, např. APC (ale ne třeba Memcache, které posílá data po síti). S ním už to je jednoduché:
<?php /** Zvýšení hodnoty logovacího čítače * @param string v úložišti už musí existovat klíč "counter.$name" * @param int * @return bool * @copyright Jakub Vrána, https://php.vrana.cz/ */ function log_counter($name, $value = 1) { apc_inc("counter.$name", $value, $return); return $return; } // příklady použití: log_counter('searches'); log_counter('page_build_time_ms', (int) $microtime * 1000); ?>
Klíč je vhodné zaregistrovat samostatně, abychom se ve funkci nemuseli zdržovat jeho vytvářením.
Takto nastavené logování není o moc dražší než $counter[$name] += $value
– data se zapisují v lokální paměti webového serveru, jen do paměti sdílené všemi procesy. Báli byste se v kódu použít $i++
, aby se aplikace příliš nezpomalila? Já tedy ne.
Teď už jen potřebujeme skript, který jednou za čas obejde všechny hodnoty na všech serverech a pošle je do společného úložiště. Může běžet třeba jednou za 15 minut nebo v závislosti na tom, jak moc podrobná data potřebujeme. Tento skript už nemusí být nijak zvlášť rychlý, protože není závislý na tom, jak často čítače zvyšujeme.
<?php /** Přesun hodnot všech čítačů do databáze * @return int počet zapsaných čítačů * @copyright Jakub Vrána, https://php.vrana.cz/ */ function log_grab() { $return = 0; foreach (new APCIterator('user', '~^counter\\.~') as $counter) { $name = preg_replace('~^counter\\.~', '', $counter['key']); $result = mysql_query(" INSERT INTO counter (name, value, logged) VALUES ('" . mysql_real_escape_string($name) . "', '" . mysql_real_escape_string($counter['value']) . "', NOW()) "); if ($result) { apc_dec($counter['key'], $counter['value']); $return++; } } return $return; } ?>
S takto navrženým logováním si můžeme dovolit nastavit prakticky libovolné čítače bez obavy o výrazné zpomalení aplikace. Logováním součtu a počtu (např. u času sestavení stránky) můžeme sledovat i průměrné hodnoty.
Diskuse je zrušena z důvodu spamu.