<?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">&raquo;&nbsp;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>&#039;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">&lt;?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">?&gt;</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&#039;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">&lt;?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">?&gt;</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">&lt;?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">-&gt;</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">-&gt;</span><span style="color: #0000BB">createQueryShape</span><span style="color: #007700">( (array) </span><span style="color: #0000BB">$event</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getCommand</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">filter </span><span style="color: #007700">);<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$event</span><span style="color: #007700">-&gt;</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">-&gt;</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">-&gt;</span><span style="color: #0000BB">pendingCommands </span><span style="color: #007700">) )<br />        {<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">queryShapeStats</span><span style="color: #007700">[</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</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">-&gt;</span><span style="color: #0000BB">queryShapeStats</span><span style="color: #007700">[</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</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">-&gt;</span><span style="color: #0000BB">getDurationMicros</span><span style="color: #007700">();<br />            unset( </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</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">-&gt;</span><span style="color: #0000BB">getRequestId</span><span style="color: #007700">(), </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</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">-&gt;</span><span style="color: #0000BB">pendingCommands</span><span style="color: #007700">[</span><span style="color: #0000BB">$event</span><span style="color: #007700">-&gt;</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">-&gt;</span><span style="color: #0000BB">queryShapeStats </span><span style="color: #007700">as </span><span style="color: #0000BB">$shape </span><span style="color: #007700">=&gt; </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">=&gt; </span><span style="color: #DD0000">'scotland-highlands'</span><span style="color: #007700">, </span><span style="color: #DD0000">'age' </span><span style="color: #007700">=&gt; [ </span><span style="color: #DD0000">'$gte' </span><span style="color: #007700">=&gt; </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">-&gt;</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">=&gt; </span><span style="color: #DD0000">'scotland-lowlands'</span><span style="color: #007700">, </span><span style="color: #DD0000">'age' </span><span style="color: #007700">=&gt; [ </span><span style="color: #DD0000">'$gte' </span><span style="color: #007700">=&gt; </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">-&gt;</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">=&gt; </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">-&gt;</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">?&gt;</span></span></code></div>
  </div>

 </div>

</div><?php manual_footer($setup); ?>