PHP 8.4.1 Released!

Surveillance de la performance de l'application (Application Performance Monitoring - APM)

L'extension contient une API d'observations événements, qui permet aux applications de surveiller les commandes et les activités internes liées à la » Spécification de découverte et de surveillance du serveur. Ce tutoriel démontrera la surveillance des commandes en utilisant l'interface MongoDB\Driver\Monitoring\CommandSubscriber.

L'interface MongoDB\Driver\Monitoring\CommandSubscriber définit trois méthodes: commandStarted, commandSucceeded, et commandFailed. Chacune de ces trois méthodes accepte un seul argument event d'une classe spécifique pour l'événement respectif. Par exemple, l'argument $event de commandSucceeded est un objet MongoDB\Driver\Monitoring\CommandSucceededEvent.

Dans ce tutoriel, nous allons implémenter un observateur qui crée une liste de tous les profils de requête et le temps moyen qu'ils ont pris.

Structure des classes d'observations

Nous commençons par le cadre de notre observateur:

<?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
{
}
}

?>

Enregistrement de l'observateur

Une fois qu'un objet observateur est instancié, il doit être enregistré avec le système de surveillance de l'extension. Cela se fait en appelant MongoDB\Driver\Monitoring\addSubscriber() ou MongoDB\Driver\Manager::addSubscriber() pour enregistrer l'observateur globalement ou avec un Manager spécifique, respectivement.

<?php

\MongoDB\Driver\Monitoring\addSubscriber
( new QueryTimeCollector() );

?>

Implémenter la logique

Avec l'objet enregistré, la seule chose qui reste est d'implémenter la logique dans la classe observatrice. Pour corréler les deux événements qui composent une commande exécutée avec succès (commandStarted et commandSucceeded), chaque objet d'événement expose un champ requestId.

Pour enregistrer le temps moyen par forme de requête, nous allons commencer par vérifier une commande find dans l'événement commandStarted. Nous allons ensuite ajouter un élément à la propriété pendingCommands indexé par son requestId et avec sa valeur représentant la forme de requête.

Si nous recevons un événement commandSucceeded correspondant avec le même requestId, nous ajoutons la durée de l'événement (depuis durationMicros) au temps total et incrémentons le compteur d'opérations.

Si un événement commandFailed correspondant est rencontré, nous supprimons simplement l'entrée de la propriété pendingCommands.

<?php

class QueryTimeCollector implements \MongoDB\Driver\Monitoring\CommandSubscriber
{
private
$pendingCommands = [];
private
$queryShapeStats = [];

/* Créer une forme de requête à partir de l'argument de filtre. Pour l'instant, il ne prend en compte que
* les champs de premier niveau */
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' );

/* Ajouter l'observateur */
\MongoDB\Driver\Monitoring\addSubscriber( new QueryTimeCollector() );

/* Faire une série de requêtes */
$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 );

?>
add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top