Sentry je vynikající nástroj pro monitoring a logování chybových stavů aplikace. Lze velmi snadno využívat jak SaaS službu, tak i na vlastní infrastruktuře díky dostupnému Docker image.
Přidání podpory do Symfony projektu je díky composeru velmi snadné
composer require sentry/sentry-symfony
V tomto zápisku popisuji jak nastavit Sentry jako monitor výkonu PHP Symfony aplikace včetně nastavení pro přehledné monitorování GraphQL API implementovaného pomocí Overblog GraphQL Bundle. Pro úplně základní nastavení aplikace stačí jednoduchá úprava souboru config/packages/sentry.yaml a to následujícím způsobem
sentry:
dsn: '%env(SENTRY_DSN)%'
options:
traces_sample_rate: '%env(float:SENTRY_PERFORMANCE_RATIO)%'
Kde
traces_sample_ratev sekcioptions- poměr měřených transakcí jako číslo mezi 0 a 1 (0.2 pak znamená, že 20 % transakcí je měřených). Na devel stage dáváme klidně 1.0, v produkčním prostředí pak třeba 0.02. 0 měření vypíná.
V dodatečném nastavení lze upřesnit co vše má být monitorováno (dbal, twig, cache, http_client, console, viz nastavení pro Symfony), proto zapnutí/vypnutí konkrétního měření je závislé na konkrétním projektu a jeho potřeb. Nyní už jenom zbývá doplnit env proměnné do .env souborů, např. takto
SENTRY_DSN=https://sentry.io/dsn-vaseho-projektu
SENTRY_PERFORMANCE_RATIO=0.05
Pokud je vše dobře nastavené, tak by se vám již s prvními requesty do aplikace měly zobrazovat výkonové charakteristiky měřených transakcí identifikované http metodou a url requestu, např. GET https://www.id-sign.com/poradna. Toto může být dostačující pro klasické stránky, kdy každý obsah má svou vlastní URL. Pokud však chceme monitorovat výkon GraphQL API, které má pro veškerý obsah jeden endpoint, potřebujeme jednotlivá volání API pojmenovat dle volané query. A ideálně si k tomu doplnit i autentikovaného uživatele, přesný zápis query použité proměnné.
V našich projektech využíváme Overblog GraphQL Bundle, který lze pro toto doplnění velmi snadno upravit. Stačí využít jednu z jeho událostí a to graphql.pre_executor. Připravíme si tedy patřičný EventListener, pojmenovaný např. GraphQLListener:
<?php
namespace App\EventListener;
use App\Entity\User;
use Overblog\GraphQLBundle\Event\ExecutorArgumentsEvent;
use Sentry\Breadcrumb;
use Sentry\SentrySdk;
use Sentry\State\Scope;
use Symfony\Bundle\SecurityBundle\Security;
use function Sentry\addBreadcrumb;
use function Sentry\captureException;
use function Sentry\configureScope;
readonly class GraphQLListener
{
public function __construct(private Security $security)
{
}
public function onPreExecutor(ExecutorArgumentsEvent $event): void
{
$name = $event->getOperationName() ?? 'Unknown operation';
$sentryTransaction = SentrySdk::getCurrentHub()->getTransaction();
$sentryTransaction?->setName($name);
$authUser = $this->security->getUser();
if ($authUser instanceof User) {
configureScope(function (Scope $scope) use ($authUser): void {
$scope->setUser([
'id' => $authUser->getId(),
]);
});
}
try {
addBreadcrumb(
new Breadcrumb(
Breadcrumb::LEVEL_INFO,
Breadcrumb::TYPE_DEFAULT,
'GraphQL',
'query',
[
'userId' => $authUser?->getId(),
'operationName' => $name,
'query' => $event->getRequestString(),
'variables' => json_encode($event->getVariableValue(), JSON_THROW_ON_ERROR),
]
)
);
} catch (\JsonException $exception) {
captureException($exception);
}
}
}
a v config/services.yaml si jej zaregistrujeme tak, aby byl volán pro výše uvedenou událost
App\EventListener\GraphQLListener:
tags:
- { name: kernel.event_listener, event: graphql.pre_executor, method: onPreExecutor }
Tímto jednoduchým rozšířením máme jednotlivé transakce
- pojmenované dle volané query - viz
$sentryTransaction?->setName(...) - doplněné o informaci o přihlášeném uživateli - viz
$scope->setUser(...) - a v breadcrumbs k celé transakci vidíme i přesné znění query a použité proměnné - viz
addBreadcrumb(...)
Možností konfigurací je mnohem více, pro další konkrétní informace doporučuji si projít oficiální dokumentaci.
Nakonec zmíním důležitou informaci plynoucí z podstaty PHP a jeho synchronnosti. Veškeré měření a komunikace se Sentry (nejspíše ve většině případů) probíhá ve stejném procesu jako zpracování měřeného requestu. Z toho plyne ovlivnění rychlosti zpracování vlastního requestu. Sentry nabízí řešení, které tento vliv snižuje téměř k nule - vytvoření lokální proxy skrze Relay, viz opět oficiální dokumentace.