Signatur
Beschreibung
Das Interface MongoDB\Driver\Monitoring\CommandSubscriber gehört zur MongoDB-Driver-Monitoring-API (SDAM/Command Monitoring). Es ermöglicht Entwicklern, eigene Klassen zu erstellen, die bei jeder Ausführung eines MongoDB-Befehls (z. B. find, insert, aggregate) automatisch benachrichtigt werden.
Implementierende Klassen müssen drei Methoden bereitstellen: commandStarted(), commandSucceeded() und commandFailed(). Diese Methoden erhalten entsprechende Ereignis-Objekte (CommandStartedEvent, CommandSucceededEvent, CommandFailedEvent), die Details wie Befehlsname, Datenbankname, Dauer und ggf. Fehlerinformationen enthalten.
Typische Einsatzgebiete sind Performance-Monitoring (Query-Laufzeiten messen), Logging aller Datenbankoperationen, Debugging von MongoDB-Abfragen sowie die Integration mit APM-Systemen (Application Performance Monitoring) wie Datadog oder New Relic.
Um einen Subscriber zu aktivieren, muss er über MongoDB\Driver\Monitoring\addSubscriber() (global) oder $manager->addSubscriber() (manager-spezifisch) registriert werden.
Beispiele
Query-Logger mit CommandSubscriber
<?php
use MongoDB\Driver\Monitoring\CommandSubscriber;
use MongoDB\Driver\Monitoring\CommandStartedEvent;
use MongoDB\Driver\Monitoring\CommandSucceededEvent;
use MongoDB\Driver\Monitoring\CommandFailedEvent;
use MongoDB\Driver\Manager;
class QueryLogger implements CommandSubscriber
{
private array $log = [];
public function commandStarted(CommandStartedEvent $event): void
{
$this->log[$event->getRequestId()] = [
'command' => $event->getCommandName(),
'database' => $event->getDatabaseName(),
'started' => microtime(true),
];
}
public function commandSucceeded(CommandSucceededEvent $event): void
{
$id = $event->getRequestId();
$duration = microtime(true) - ($this->log[$id]['started'] ?? microtime(true));
echo sprintf(
"[OK] %s.%s — %.4f ms\n",
$this->log[$id]['database'] ?? '?',
$this->log[$id]['command'] ?? '?',
$duration * 1000
);
unset($this->log[$id]);
}
public function commandFailed(CommandFailedEvent $event): void
{
$id = $event->getRequestId();
echo sprintf(
"[ERR] %s — %s\n",
$this->log[$id]['command'] ?? '?',
$event->getError()->getMessage()
);
unset($this->log[$id]);
}
}
$manager = new Manager('mongodb://localhost:27017');
$logger = new QueryLogger();
$manager->addSubscriber($logger);
// Ab hier werden alle über $manager ausgeführten Befehle geloggt.
// Beispiel: $manager->executeCommand(...);
Globale Registrierung für alle Manager-Instanzen
<?php
use MongoDB\Driver\Monitoring\CommandSubscriber;
use MongoDB\Driver\Monitoring\CommandStartedEvent;
use MongoDB\Driver\Monitoring\CommandSucceededEvent;
use MongoDB\Driver\Monitoring\CommandFailedEvent;
class SimpleCommandLogger implements CommandSubscriber
{
public function commandStarted(CommandStartedEvent $event): void
{
echo "START: " . $event->getCommandName() . "\n";
}
public function commandSucceeded(CommandSucceededEvent $event): void
{
echo "OK: " . $event->getCommandName() . "\n";
}
public function commandFailed(CommandFailedEvent $event): void
{
echo "FAIL: " . $event->getCommandName() . " — " . $event->getError()->getMessage() . "\n";
}
}
// Globale Registrierung: gilt für ALLE nachfolgend erstellten Manager-Instanzen
MongoDB\Driver\Monitoring\addSubscriber(new SimpleCommandLogger());
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
// Alle Befehle über $manager lösen nun den SimpleCommandLogger aus.
// Wichtig · Fallstricke
Sicherheitshinweis: Die Ereignis-Objekte können vollständige Befehlsdokumente enthalten, die sensible Daten (z. B. Passwörter bei authenticate-Befehlen) beinhalten können. MongoDB maskiert bekannte sensible Felder automatisch, dennoch sollten Log-Ausgaben nicht ungesichert persistiert oder übertragen werden.
Performance: Da jede Datenbankoperation alle registrierten Subscriber synchron aufruft, können aufwändige Operationen in den Methoden die Gesamtperformance der Anwendung spürbar beeinflussen. Subscriber-Implementierungen sollten daher möglichst schnell sein und teure Operationen (z. B. I/O) asynchron auslagern.
Das Interface erweitert MongoDB\Driver\Monitoring\Subscriber, das als Marker-Interface dient. Subscriber können über MongoDB\Driver\Monitoring\removeSubscriber() bzw. $manager->removeSubscriber() wieder deregistriert werden.