<?php include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc'; $TOC = array(); $TOC_DEPRECATED = array(); $PARENTS = array(); include_once dirname(__FILE__) ."/toc/mongodb.tutorial.inc"; $setup = array ( 'home' => array ( 0 => 'index.php', 1 => 'PHP Manual', ), 'head' => array ( 0 => 'UTF-8', 1 => 'tr', ), 'this' => array ( 0 => 'mongodb.tutorial.apm.php', 1 => 'Application Performance Monitoring (APM)', ), 'up' => array ( 0 => 'mongodb.tutorial.php', 1 => 'Tutorials', ), 'prev' => array ( 0 => 'mongodb.tutorial.library.php', 1 => 'Using the PHP Library for MongoDB (PHPLIB)', ), 'next' => array ( 0 => 'mongodb.architecture.php', 1 => 'Driver Architecture and Internals', ), 'alternatives' => array ( ), 'source' => array ( 'lang' => 'en', 'path' => 'reference/mongodb/tutorial/apm.xml', ), 'history' => array ( ), ); $setup["toc"] = $TOC; $setup["toc_deprecated"] = $TOC_DEPRECATED; $setup["parents"] = $PARENTS; manual_setup($setup); contributors($setup); ?> <div id="mongodb.tutorial.apm" class="section"> <h2 class="title">Application Performance Monitoring (APM)</h2> <p class="para"> The extension contains an event subscriber API, which allows applications to monitor commands and internal activity pertaining to the <a href="https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.md" class="link external">» Server Discovery and Monitoring Specification</a>. This tutorial will demonstrate command monitoring using the <span class="classname"><a href="class.mongodb-driver-monitoring-commandsubscriber.php" class="classname">MongoDB\Driver\Monitoring\CommandSubscriber</a></span> interface. </p> <p class="para"> The <span class="classname"><a href="class.mongodb-driver-monitoring-commandsubscriber.php" class="classname">MongoDB\Driver\Monitoring\CommandSubscriber</a></span> interface defines three methods: <code class="literal">commandStarted</code>, <code class="literal">commandSucceeded</code>, and <code class="literal">commandFailed</code>. Each of these three methods accept a single <code class="parameter">event</code> argument of a specific class for the respective event. For example, the <code class="literal">commandSucceeded</code>'s <code class="parameter">$event</code> argument is a <span class="classname"><a href="class.mongodb-driver-monitoring-commandsucceededevent.php" class="classname">MongoDB\Driver\Monitoring\CommandSucceededEvent</a></span> object. </p> <p class="para"> In this tutorial we will implement a subscriber that creates a list of all the query profiles and the average time they took. </p> <div class="section"> <h2 class="title">Subscriber Class Scaffolding</h2> <p class="para"> We start with the framework for our subscriber: </p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">QueryTimeCollector </span><span style="color: #007700">implements </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandSubscriber<br /></span><span style="color: #007700">{<br /> public function </span><span style="color: #0000BB">commandStarted</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandStartedEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> }<br /><br /> public function </span><span style="color: #0000BB">commandSucceeded</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandSucceededEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> }<br /><br /> public function </span><span style="color: #0000BB">commandFailed</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandFailedEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> }<br />}<br /><br /></span><span style="color: #0000BB">?></span></span></code></div> </div> </div> <div class="section"> <h2 class="title">Registering the Subscriber</h2> <p class="para"> Once a subscriber object is instantiated, it needs to be registered with the extensions's monitoring system. This is done by calling <span class="methodname"><a href="function.mongodb.driver.monitoring.addsubscriber.php" class="methodname">MongoDB\Driver\Monitoring\addSubscriber()</a></span> or <span class="methodname"><a href="mongodb-driver-manager.addsubscriber.php" class="methodname">MongoDB\Driver\Manager::addSubscriber()</a></span> to register the subscriber globally or with a specific Manager, respectively. </p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /><br />\MongoDB\Driver\Monitoring\addSubscriber</span><span style="color: #007700">( new </span><span style="color: #0000BB">QueryTimeCollector</span><span style="color: #007700">() );<br /><br /></span><span style="color: #0000BB">?></span></span></code></div> </div> </div> <div class="section"> <h2 class="title">Implementing the Logic</h2> <p class="para"> With the object registered, the only thing left is to implement the logic in the subscriber class. To correlate the two events that make up a successfully executed command (commandStarted and commandSucceeded), each event object exposes a <code class="literal">requestId</code> field. </p> <p class="para"> To record the average time per query shape, we will start by checking for a <code class="literal">find</code> command in the commandStarted event. We will then add an item to the <code class="literal">pendingCommands</code> property indexed by its <code class="literal">requestId</code> and with its value representing the query shape. </p> <p class="para"> If we receive a corresponding commandSucceeded event with the same <code class="literal">requestId</code>, we add the duration of the event (from <code class="literal">durationMicros</code>) to the total time and increment the operation count. </p> <p class="para"> If a corresponding commandFailed event is encountered, we just remove the entry from the <code class="literal">pendingCommands</code> property. </p> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB"><?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">QueryTimeCollector </span><span style="color: #007700">implements </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandSubscriber<br /></span><span style="color: #007700">{<br /> private </span><span style="color: #0000BB">$pendingCommands </span><span style="color: #007700">= [];<br /> private </span><span style="color: #0000BB">$queryShapeStats </span><span style="color: #007700">= [];<br /><br /> </span><span style="color: #FF8000">/* Creates a query shape out of the filter argument. Right now it only<br /> * takes the top level fields into account */<br /> </span><span style="color: #007700">private function </span><span style="color: #0000BB">createQueryShape</span><span style="color: #007700">( array </span><span style="color: #0000BB">$filter </span><span style="color: #007700">)<br /> {<br /> return </span><span style="color: #0000BB">json_encode</span><span style="color: #007700">( </span><span style="color: #0000BB">array_keys</span><span style="color: #007700">( </span><span style="color: #0000BB">$filter </span><span style="color: #007700">) );<br /> }<br /><br /> public function </span><span style="color: #0000BB">commandStarted</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandStartedEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> if ( </span><span style="color: #DD0000">'find' </span><span style="color: #007700">=== </span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getCommandName</span><span style="color: #007700">() )<br /> {<br /> </span><span style="color: #0000BB">$queryShape </span><span style="color: #007700">= </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">createQueryShape</span><span style="color: #007700">( (array) </span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getCommand</span><span style="color: #007700">()-></span><span style="color: #0000BB">filter </span><span style="color: #007700">);<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getRequestId</span><span style="color: #007700">()] = </span><span style="color: #0000BB">$queryShape</span><span style="color: #007700">;<br /> }<br /> }<br /><br /> public function </span><span style="color: #0000BB">commandSucceeded</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandSucceededEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> </span><span style="color: #0000BB">$requestId </span><span style="color: #007700">= </span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getRequestId</span><span style="color: #007700">();<br /> if ( </span><span style="color: #0000BB">array_key_exists</span><span style="color: #007700">( </span><span style="color: #0000BB">$requestId</span><span style="color: #007700">, </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands </span><span style="color: #007700">) )<br /> {<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">queryShapeStats</span><span style="color: #007700">[</span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$requestId</span><span style="color: #007700">]][</span><span style="color: #DD0000">'count'</span><span style="color: #007700">]++;<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">queryShapeStats</span><span style="color: #007700">[</span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$requestId</span><span style="color: #007700">]][</span><span style="color: #DD0000">'duration'</span><span style="color: #007700">] += </span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getDurationMicros</span><span style="color: #007700">();<br /> unset( </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$requestId</span><span style="color: #007700">] );<br /> }<br /> }<br /><br /> public function </span><span style="color: #0000BB">commandFailed</span><span style="color: #007700">( </span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\CommandFailedEvent $event </span><span style="color: #007700">): </span><span style="color: #0000BB">void<br /> </span><span style="color: #007700">{<br /> if ( </span><span style="color: #0000BB">array_key_exists</span><span style="color: #007700">( </span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getRequestId</span><span style="color: #007700">(), </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands </span><span style="color: #007700">) )<br /> {<br /> unset( </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$event</span><span style="color: #007700">-></span><span style="color: #0000BB">getRequestId</span><span style="color: #007700">()] );<br /> }<br /> }<br /><br /> public function </span><span style="color: #0000BB">__destruct</span><span style="color: #007700">()<br /> {<br /> foreach( </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">queryShapeStats </span><span style="color: #007700">as </span><span style="color: #0000BB">$shape </span><span style="color: #007700">=> </span><span style="color: #0000BB">$stats </span><span style="color: #007700">)<br /> {<br /> echo </span><span style="color: #DD0000">"Shape: "</span><span style="color: #007700">, </span><span style="color: #0000BB">$shape</span><span style="color: #007700">, </span><span style="color: #DD0000">" ("</span><span style="color: #007700">, </span><span style="color: #0000BB">$stats</span><span style="color: #007700">[</span><span style="color: #DD0000">'count'</span><span style="color: #007700">], </span><span style="color: #DD0000">")\n "</span><span style="color: #007700">,<br /> </span><span style="color: #0000BB">$stats</span><span style="color: #007700">[</span><span style="color: #DD0000">'duration'</span><span style="color: #007700">] / </span><span style="color: #0000BB">$stats</span><span style="color: #007700">[</span><span style="color: #DD0000">'count'</span><span style="color: #007700">], </span><span style="color: #DD0000">"µs\n\n"</span><span style="color: #007700">;<br /> }<br /> }<br />}<br /><br /></span><span style="color: #0000BB">$m </span><span style="color: #007700">= new </span><span style="color: #0000BB">\MongoDB\Driver\Manager</span><span style="color: #007700">( </span><span style="color: #DD0000">'mongodb://localhost:27016' </span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">/* Add the subscriber */<br /></span><span style="color: #0000BB">\MongoDB\Driver\Monitoring\addSubscriber</span><span style="color: #007700">( new </span><span style="color: #0000BB">QueryTimeCollector</span><span style="color: #007700">() );<br /><br /></span><span style="color: #FF8000">/* Do a bunch of queries */<br /></span><span style="color: #0000BB">$query </span><span style="color: #007700">= new </span><span style="color: #0000BB">\MongoDB\Driver\Query</span><span style="color: #007700">( [<br /> </span><span style="color: #DD0000">'region_slug' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'scotland-highlands'</span><span style="color: #007700">, </span><span style="color: #DD0000">'age' </span><span style="color: #007700">=> [ </span><span style="color: #DD0000">'$gte' </span><span style="color: #007700">=> </span><span style="color: #0000BB">20 </span><span style="color: #007700">]<br />] );<br /></span><span style="color: #0000BB">$cursor </span><span style="color: #007700">= </span><span style="color: #0000BB">$m</span><span style="color: #007700">-></span><span style="color: #0000BB">executeQuery</span><span style="color: #007700">( </span><span style="color: #DD0000">'dramio.whisky'</span><span style="color: #007700">, </span><span style="color: #0000BB">$query </span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$query </span><span style="color: #007700">= new </span><span style="color: #0000BB">\MongoDB\Driver\Query</span><span style="color: #007700">( [<br /> </span><span style="color: #DD0000">'region_slug' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'scotland-lowlands'</span><span style="color: #007700">, </span><span style="color: #DD0000">'age' </span><span style="color: #007700">=> [ </span><span style="color: #DD0000">'$gte' </span><span style="color: #007700">=> </span><span style="color: #0000BB">15 </span><span style="color: #007700">]<br />] );<br /></span><span style="color: #0000BB">$cursor </span><span style="color: #007700">= </span><span style="color: #0000BB">$m</span><span style="color: #007700">-></span><span style="color: #0000BB">executeQuery</span><span style="color: #007700">( </span><span style="color: #DD0000">'dramio.whisky'</span><span style="color: #007700">, </span><span style="color: #0000BB">$query </span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$query </span><span style="color: #007700">= new </span><span style="color: #0000BB">\MongoDB\Driver\Query</span><span style="color: #007700">( [ </span><span style="color: #DD0000">'region_slug' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'scotland-lowlands' </span><span style="color: #007700">] );<br /></span><span style="color: #0000BB">$cursor </span><span style="color: #007700">= </span><span style="color: #0000BB">$m</span><span style="color: #007700">-></span><span style="color: #0000BB">executeQuery</span><span style="color: #007700">( </span><span style="color: #DD0000">'dramio.whisky'</span><span style="color: #007700">, </span><span style="color: #0000BB">$query </span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?></span></span></code></div> </div> </div> </div><?php manual_footer($setup); ?>