1
0
mirror of https://github.com/php/doc-ru.git synced 2026-03-24 07:42:22 +01:00
Files
2024-10-21 21:58:28 +03:00

197 lines
7.7 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 3e871fe7eab38f9b0398569c57a1dd0c21e69652 Maintainer: rjhdby Status: ready -->
<!-- Reviewed: no -->
<section xml:id="mongodb.tutorial.apm" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Мониторинг производительности приложения (Application Performance Monitoring, или APM)</title>
<para>
Модуль содержит API-интерфейс подписчика события, который разрешает приложениям отслеживать команды и внутреннюю активность,
которая относится к <link xlink:href="&url.mongodb.sdam;">Спецификации обнаружения и мониторинга серверов</link>.
Это руководство продемонстрирует мониторинг команд
через интерфейс <classname>MongoDB\Driver\Monitoring\CommandSubscriber</classname>.
</para>
<para>
Интерфейс <classname>MongoDB\Driver\Monitoring\CommandSubscriber</classname>
определяет три метода: <literal>commandStarted</literal>,
<literal>commandSucceeded</literal> и <literal>commandFailed</literal>.
Каждый из них принимает один параметр <parameter>event</parameter> класса,
соответствующего нужному событию. К примеру, <literal>commandSucceeded</literal>
принимает аргумент <parameter>$event</parameter> класса
<classname>MongoDB\Driver\Monitoring\CommandSucceededEvent</classname>.
</para>
<para>
Руководство реализует подписчика, который создаст список
профилировок каждого запроса и среднего времени, которое заняли запросы.
</para>
<section>
<title>Класс-подписчик Scaffolding</title>
<para>
Начнём с шаблона для подписчика:
</para>
<programlisting role="php">
<![CDATA[
<?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 {}
}
?>
]]>
</programlisting>
</section>
<section>
<title>Регистрация подписчика</title>
<para>
Как только объект подписчика создали, подписчика необходимо зарегистрировать
в системе мониторинга модуля. Глобально подписчика регистрируют методом
<methodname>MongoDB\Driver\Monitoring\addSubscriber</methodname>,
а для конкретного объекта класса Manager — методом
<methodname>MongoDB\Driver\Manager::addSubscriber</methodname>.
</para>
<programlisting role="php">
<![CDATA[
<?php
\MongoDB\Driver\Monitoring\addSubscriber( new QueryTimeCollector() );
?>
]]>
</programlisting>
</section>
<section>
<title>Реализуем логику</title>
<para>
Теперь займёмся реализацией логики класа подписчика.
Для сопоставления двух событий, относящихся к успешно выполненной
команды (commandStarted and commandSucceeded), каждый объект события
предоставляет поле <literal>requestId</literal>.
</para>
<para>
Для записи среднего времени выполнения запроса мы начнём с
отслеживания команды <literal>find</literal> в событии commandStarted.
Мы будем добавлять элемент в массив <literal>pendingCommands</literal>
с индексом соответствующим <literal>requestId</literal> и значением, соответствующим
запросу.
</para>
<para>
Когда мы получим соответствующее событие commandSucceeded с соответствующим
<literal>requestId</literal>, мы добавим время выполнения (из
<literal>durationMicros</literal>) к общему времени и увеличим счётчик операций.
</para>
<para>
Если мы получим событие commandFailed, мы просто удалим соответствующую запись из
<literal>pendingCommands</literal>.
</para>
<programlisting role="php">
<![CDATA[
<?php
class QueryTimeCollector implements \MongoDB\Driver\Monitoring\CommandSubscriber
{
private $pendingCommands = [];
private $queryShapeStats = [];
/* Создаёт форму запроса из аргумента фильтра. Учитываются
* только поля верхнего уровня. */
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');
/* Добавляем подписчика */
\MongoDB\Driver\Monitoring\addSubscriber(new QueryTimeCollector());
/* Запускаем пачку запросов */
$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);
?>
]]>
</programlisting>
</section>
</section>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->