Надгледување на перформансите на апликацијата (APM)
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Надгледување на перформансите на апликацијата (APM)
Референца за `mongodb.tutorial.apm.php` со подобрена типографија и навигација.
Надгледување на перформансите на апликацијата (APM)
Екстензијата содржи API за претплатник на настани, кој им овозможува на апликациите да ги следат командите и внатрешните активности што се однесуваат на » Спецификација за откривање и следење на сервери. Овој туторијал ќе демонстрира следење на команди користејќи го MongoDB\Driver\Monitoring\CommandSubscriber interface.
На MongoDB\Driver\Monitoring\CommandSubscriber
интерфејсот дефинира три методи: commandStarted,
commandSucceededПрепорачаниот начин за избегнување на SQL инјекција е со врзување на сите податоци преку подготвени изрази. Користењето на параметризирани прашања не е доволно за целосно избегнување на SQL инјекција, но тоа е најлесниот и најбезбедниот начин за обезбедување влез во SQL изразите. Сите динамични литерали на податоци во commandFailed. Секој од овие три методи прифаќа еден event
аргумент од специфична класа за соодветниот настан. На пример,
commandSucceededпри обид за десериализација на недефинирана класа или класа што не е наведена во $event аргументот е MongoDB\Driver\Monitoring\CommandSucceededEvent
object.
Во овој туторијал ќе имплементираме претплатник што создава список од сите профили на команди и просечното време што им е потребно.
Структура на класата за претплатник
Започнуваме со рамката за нашиот претплатник:
<?php
class QueryTimeCollector implements \MongoDB\Driver\Monitoring\CommandSubscriber
{
public function commandStarted( \MongoDB\Driver\Monitoring\CommandStartedEvent $event ): void
{
}
public function commandSucceeded( \MongoDB\Driver\Monitoring\CommandSucceededEvent $event ): void
{
}
public function commandFailed( \MongoDB\Driver\Monitoring\CommandFailedEvent $event ): void
{
}
}
?>Регистрирање на претплатникот
Откако ќе се инстанцира објект за претплатник, тој мора да се регистрира во системот за следење на екстензијата. Ова се прави со повикување на Името на компонентата на драјверот што ја емитувала лог пораката. or (mongodb >=1.10.0) за да го регистрирате претплатникот глобално или со специфичен Менаџер, соодветно.
<?php
\MongoDB\Driver\Monitoring\addSubscriber( new QueryTimeCollector() );
?>Имплементирање на логиката
Со регистриран објект, единственото нешто што останува е да се имплементира логиката во класата за претплатник. За да ги поврземе двата настани што сочинуваат успешно извршена команда (commandStarted и commandSucceeded), секој објект од настанот изложува requestId field.
За да го запишеме просечното време по облик на команда, прво ќе провериме за
find команда во настанот commandStarted. Потоа ќе додадеме ставка во pendingCommands својство индексирано по неговиот
requestId и чија вредност го претставува обликот на барањето.
Ако добиеме соодветен настан commandSucceeded со истото
requestId, ја додаваме времетраењето на настанот (од
durationMicros) на вкупното време и го зголемуваме бројот на операции.
Ако се наиде на соодветен настан commandFailed, едноставно го отстрануваме записот од pendingCommands property.
<?php
class QueryTimeCollector implements \MongoDB\Driver\Monitoring\CommandSubscriber
{
private $pendingCommands = [];
private $queryShapeStats = [];
/* Creates a query shape out of the filter argument. Right now it only
* takes the top level fields into account */
private function createQueryShape( array $filter )
{
return json_encode( array_keys( $filter ) );
}
public function commandStarted( \MongoDB\Driver\Monitoring\CommandStartedEvent $event ): void
{
if ( 'find' === $event->getCommandName() )
{
$queryShape = $this->createQueryShape( (array) $event->getCommand()->filter );
$this->pendingCommands[$event->getRequestId()] = $queryShape;
}
}
public function commandSucceeded( \MongoDB\Driver\Monitoring\CommandSucceededEvent $event ): void
{
$requestId = $event->getRequestId();
if ( array_key_exists( $requestId, $this->pendingCommands ) )
{
$this->queryShapeStats[$this->pendingCommands[$requestId]]['count']++;
$this->queryShapeStats[$this->pendingCommands[$requestId]]['duration'] += $event->getDurationMicros();
unset( $this->pendingCommands[$requestId] );
}
}
public function commandFailed( \MongoDB\Driver\Monitoring\CommandFailedEvent $event ): void
{
if ( array_key_exists( $event->getRequestId(), $this->pendingCommands ) )
{
unset( $this->pendingCommands[$event->getRequestId()] );
}
}
public function __destruct()
{
foreach( $this->queryShapeStats as $shape => $stats )
{
echo "Shape: ", $shape, " (", $stats['count'], ")\n ",
$stats['duration'] / $stats['count'], "µs\n\n";
}
}
}
$m = new \MongoDB\Driver\Manager( 'mongodb://localhost:27016' );
/* Add the subscriber */
\MongoDB\Driver\Monitoring\addSubscriber( new QueryTimeCollector() );
/* Do a bunch of queries */
$query = new \MongoDB\Driver\Query( [
'region_slug' => 'scotland-highlands', 'age' => [ '$gte' => 20 ]
] );
$cursor = $m->executeQuery( 'dramio.whisky', $query );
$query = new \MongoDB\Driver\Query( [
'region_slug' => 'scotland-lowlands', 'age' => [ '$gte' => 15 ]
] );
$cursor = $m->executeQuery( 'dramio.whisky', $query );
$query = new \MongoDB\Driver\Query( [ 'region_slug' => 'scotland-lowlands' ] );
$cursor = $m->executeQuery( 'dramio.whisky', $query );
?>