Bladeren bron

merged noelg/profiler

Fabien Potencier 14 jaren geleden
bovenliggende
commit
ad3b7e912d

+ 20 - 5
src/Symfony/Bundle/FrameworkBundle/Profiler/ProfilerListener.php

@@ -46,6 +46,19 @@ class ProfilerListener
         $this->onlyException = $onlyException;
     }
 
+    /**
+     * Handles the core.request event
+     *
+     * This method initialize the profiler to be able to get it as a scoped
+     * service when handleResponse() will collect the sub request
+     *
+     * @param EventInterface $event An EventInterface instance
+     */
+    public function handleRequest(EventInterface $event)
+    {
+        $this->container->get('profiler');
+    }
+
     /**
      * Handles the core.exception event.
      *
@@ -71,10 +84,6 @@ class ProfilerListener
      */
     public function handleResponse(EventInterface $event, Response $response)
     {
-        if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) {
-            return $response;
-        }
-
         if (null !== $this->matcher && !$this->matcher->matches($event->get('request'))) {
             return $response;
         }
@@ -83,7 +92,13 @@ class ProfilerListener
             return $response;
         }
 
-        $this->container->get('profiler')->collect($event->get('request'), $response, $this->exception);
+        $profiler = $this->container->get('profiler');
+
+        if (($parent = $this->container->getCurrentScopedStack('request'))) {
+            $profiler->setParent($parent['request']['profiler']->getToken());
+        }
+
+        $profiler->collect($event->get('request'), $response, $this->exception);
         $this->exception = null;
 
         return $response;

+ 1 - 0
src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml

@@ -25,6 +25,7 @@
         <service id="profiler_listener" class="%profiler_listener.class%">
             <tag name="kernel.listener" event="core.response" method="handleResponse" />
             <tag name="kernel.listener" event="core.exception" method="handleException" />
+            <tag name="kernel.listener" event="core.request" method="handleRequest" />
             <argument type="service" id="service_container" />
             <argument type="service" id="profiler.request_matcher" on-invalid="null" />
             <argument /> <!-- Only exceptions? -->

+ 17 - 0
src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig

@@ -97,4 +97,21 @@
             <em>No request session attributes</em>
         </p>
     {% endif %}
+
+
+    {% if profiler.parent %}
+        <h2><a href="{{ path('_profiler', { 'token': profiler.parent }) }}">Parent request: {{ profiler.parent }}</a></h2>
+
+        {% include 'WebProfilerBundle:Profiler:bag.html.twig' with { 'bag': profiler.parenttoken.get('request').requestattributes } only %}
+    {% endif %}
+
+    {% if profiler.children|length %}
+        <h2>Sub requests</h2>
+
+        {% for subrequest in profiler.children %}
+            <h3><a href="{{ path('_profiler', { 'token': subrequest.token }) }}">{{ subrequest.token }}</a></h3>
+            {% include 'WebProfilerBundle:Profiler:bag.html.twig' with { 'bag': subrequest.get('request').requestattributes } only %}
+        {% endfor %}
+    {% endif %}
+
 {% endblock %}

+ 16 - 0
src/Symfony/Component/DependencyInjection/Container.php

@@ -301,6 +301,22 @@ class Container implements ContainerInterface
         $this->scopedServices[$name] = array();
     }
 
+
+    /**
+     * Returns the current stacked service scope for the given name
+     *
+     * @param string $name The service name
+     * @return array The service scope
+     */
+    public function getCurrentScopedStack($name)
+    {
+        if (!isset($this->scopeStacks[$name]) || 0 === $this->scopeStacks[$name]->count()) {
+            return null;
+        }
+
+        return $this->scopeStacks[$name]->current();
+    }
+
     /**
      * This is called to leave the current scope, and move back to the parent
      * scope.

+ 16 - 3
src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php

@@ -53,12 +53,25 @@ abstract class PdoProfilerStorage implements ProfilerStorageInterface
         $criteria = $criteria ? 'WHERE '.implode(' AND ', $criteria) : '';
 
         $db = $this->initDb();
-        $tokens = $this->fetch($db, 'SELECT token, ip, url, time FROM data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $limit), $args);
+        $tokens = $this->fetch($db, 'SELECT token, ip, url, time, parent FROM data '.$criteria.' ORDER BY time DESC LIMIT '.((integer) $limit), $args);
         $this->close($db);
 
         return $tokens;
     }
 
+    /**
+     * {@inheritdoc}
+     */
+     public function findChildren($token)
+     {
+         $db = $this->initDb();
+         $args = array(':token' => $token);
+         $tokens = $this->fetch($db, 'SELECT token FROM data WHERE parent = :token LIMIT 1', $args);
+         $this->close($db);
+
+        return $tokens;
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -66,10 +79,10 @@ abstract class PdoProfilerStorage implements ProfilerStorageInterface
     {
         $db = $this->initDb();
         $args = array(':token' => $token);
-        $data = $this->fetch($db, 'SELECT data, ip, url, time FROM data WHERE token = :token LIMIT 1', $args);
+        $data = $this->fetch($db, 'SELECT data, parent, ip, url, time FROM data WHERE token = :token LIMIT 1', $args);
         $this->close($db);
         if (isset($data[0]['data'])) {
-            return array($data[0]['data'], $data[0]['ip'], $data[0]['url'], $data[0]['time']);
+            return array($data[0]['data'], $data[0]['parent'], $data[0]['ip'], $data[0]['url'], $data[0]['time']);
         }
 
         return false;

+ 43 - 2
src/Symfony/Component/HttpKernel/Profiler/Profiler.php

@@ -35,6 +35,7 @@ class Profiler
     protected $url;
     protected $time;
     protected $empty;
+    protected $children;
 
     /**
      * Constructor.
@@ -142,7 +143,7 @@ class Profiler
         $this->token = $token;
 
         if (false !== $items = $this->storage->read($token)) {
-            list($data, $this->ip, $this->url, $this->time) = $items;
+            list($data, $this->parent, $this->ip, $this->url, $this->time) = $items;
             $this->set(unserialize(base64_decode($data)));
 
             $this->empty = false;
@@ -151,6 +152,30 @@ class Profiler
         }
     }
 
+    /**
+     * Sets the parent token
+     *
+     * @param string $parent The parent token
+     */
+    public function setParent($parent)
+    {
+        $this->parent = $parent;
+    }
+
+    /**
+     * Returns an instance of the parent token
+     *
+     * @return Profiler
+     */
+    public function getParentToken()
+    {
+        if (null !== $this->parent) {
+            return $this->loadFromToken($this->parent);
+        }
+
+        return null;
+    }
+
     /**
      * Gets the token.
      *
@@ -229,6 +254,23 @@ class Profiler
         return $this->storage->find($ip, $url, $limit);
     }
 
+    /**
+     * Finds children profilers.
+     *
+     * @return array An array of Profiler
+     */
+    public function getChildren()
+    {
+        if (null === $this->children) {
+            $this->children = array();
+            foreach ($this->storage->findChildren($this->token) as $token) {
+                $this->children[] = $this->loadFromToken($token['token']);
+            }
+        }
+
+        return $this->children;
+    }
+
     /**
      * Collects data for the given Response.
      *
@@ -248,7 +290,6 @@ class Profiler
             $collector->collect($request, $response, $exception);
         }
 
-        $this->parent = '';
         $this->ip     = $request->server->get('REMOTE_ADDR');
         $this->url    = $request->getUri();
         $this->time   = time();

+ 9 - 0
src/Symfony/Component/HttpKernel/Profiler/ProfilerStorageInterface.php

@@ -29,6 +29,15 @@ interface ProfilerStorageInterface
      */
     function find($ip, $url, $limit);
 
+    /**
+     * Finds profiler tokens for the given parent token.
+     *
+     * @param string $token    The parent token
+     *
+     * @return array An array of tokens
+     */
+    function findChildren($token);
+
     /**
      * Reads data associated with the given token.
      *