Модуль содержит API-интерфейс подписчика события, который разрешает приложениям отслеживать команды и внутреннюю активность, которая относится к » Спецификации обнаружения и мониторинга серверов. Это руководство продемонстрирует мониторинг команд через интерфейс MongoDB\Driver\Monitoring\CommandSubscriber.
Интерфейс MongoDB\Driver\Monitoring\CommandSubscriber
определяет три метода: commandStarted
,
commandSucceeded
и commandFailed
.
Каждый из них принимает один параметр event
класса,
соответствующего нужному событию. К примеру, commandSucceeded
принимает аргумент $event
класса
MongoDB\Driver\Monitoring\CommandSucceededEvent.
Руководство реализует подписчика, который создаст список профилировок каждого запроса и среднего времени, которое заняли запросы.
Начнём с шаблона для подписчика:
<?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 {}
}
?>
Как только объект подписчика создали, подписчика необходимо зарегистрировать в системе мониторинга модуля. Глобально подписчика регистрируют методом MongoDB\Driver\Monitoring\addSubscriber(), а для конкретного объекта класса Manager — методом MongoDB\Driver\Manager::addSubscriber().
<?php
\MongoDB\Driver\Monitoring\addSubscriber( new QueryTimeCollector() );
?>
Теперь займёмся реализацией логики класа подписчика.
Для сопоставления двух событий, относящихся к успешно выполненной
команды (commandStarted and commandSucceeded), каждый объект события
предоставляет поле requestId
.
Для записи среднего времени выполнения запроса мы начнём с
отслеживания команды find
в событии commandStarted.
Мы будем добавлять элемент в массив pendingCommands
с индексом соответствующим requestId
и значением, соответствующим
запросу.
Когда мы получим соответствующее событие commandSucceeded с соответствующим
requestId
, мы добавим время выполнения (из
durationMicros
) к общему времени и увеличим счётчик операций.
Если мы получим событие commandFailed, мы просто удалим соответствующую запись из
pendingCommands
.
<?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);
?>