Browse Source

[WebBundle] refactored the data collector sub-system (WIP)

Fabien Potencier 15 years ago
parent
commit
22e310e240

+ 4 - 6
src/Symfony/Framework/DoctrineBundle/Debug/DoctrineDataCollector.php

@@ -21,19 +21,17 @@ use Symfony\Framework\WebBundle\Debug\DataCollector\DataCollector;
  */
 class DoctrineDataCollector extends DataCollector
 {
-  protected $data;
-
-  public function collect()
+  protected function collect()
   {
-    $this->data = array();
+    $data = array();
     if ($this->container->hasService('doctrine.dbal.logger'))
     {
-      $this->data = array(
+      $data = array(
         'queries' => $this->container->getDoctrine_Dbal_LoggerService()->queries,
       );
     }
 
-    return $this->data;
+    return $data;
   }
 
   public function getSummary()

+ 2 - 4
src/Symfony/Framework/WebBundle/Debug/DataCollector/AppDataCollector.php

@@ -19,13 +19,11 @@ namespace Symfony\Framework\WebBundle\Debug\DataCollector;
  */
 class AppDataCollector extends DataCollector
 {
-  protected $data;
-
-  public function collect()
+  protected function collect()
   {
     $request = $this->container->getRequestService();
 
-    return $this->data = array(
+    return array(
       'route'        => $request->getPathParameter('_route') ? $request->getPathParameter('_route') : '<span style="color: #a33">NONE</span>',
       'format'       => $request->getRequestFormat(),
       'content_type' => $this->manager->getResponse()->getHeader('Content-Type') ? $this->manager->getResponse()->getHeader('Content-Type') : 'text/html',

+ 3 - 5
src/Symfony/Framework/WebBundle/Debug/DataCollector/ConfigDataCollector.php

@@ -21,14 +21,12 @@ use Symfony\Foundation\Kernel;
  */
 class ConfigDataCollector extends DataCollector
 {
-  protected $data;
-
-  public function collect()
+  protected function collect()
   {
     $kernel = $this->container->getKernelService();
 
-    return $this->data = array(
-      'token'           => $this->manager->getToken(),
+    return array(
+      'token'           => $this->manager->getRequestDebugData()->getToken(),
       'symfony_version' => Kernel::VERSION,
       'name'            => $kernel->getName(),
       'env'             => $kernel->getEnvironment(),

+ 13 - 0
src/Symfony/Framework/WebBundle/Debug/DataCollector/DataCollector.php

@@ -23,12 +23,25 @@ abstract class DataCollector implements DataCollectorInterface
 {
   protected $manager;
   protected $container;
+  protected $data;
 
   public function __construct(ContainerInterface $container)
   {
     $this->container = $container;
   }
 
+  public function getData()
+  {
+    if (null === $this->data)
+    {
+      $this->data = $this->collect();
+    }
+
+    return $this->data;
+  }
+
+  abstract protected function collect();
+
   public function setCollectorManager(DataCollectorManager $manager)
   {
     $this->manager = $manager;

+ 1 - 1
src/Symfony/Framework/WebBundle/Debug/DataCollector/DataCollectorInterface.php

@@ -21,7 +21,7 @@ interface DataCollectorInterface
 {
   public function setCollectorManager(DataCollectorManager $manager);
 
-  public function collect();
+  public function getData();
 
   public function getName();
 }

+ 31 - 36
src/Symfony/Framework/WebBundle/Debug/DataCollector/DataCollectorManager.php

@@ -5,6 +5,7 @@ namespace Symfony\Framework\WebBundle\Debug\DataCollector;
 use Symfony\Components\DependencyInjection\ContainerInterface;
 use Symfony\Components\EventDispatcher\Event;
 use Symfony\Components\RequestHandler\Response;
+use Symfony\Framework\WebBundle\Debug\RequestDebugData;
 
 /*
  * This file is part of the symfony framework.
@@ -24,15 +25,16 @@ use Symfony\Components\RequestHandler\Response;
 class DataCollectorManager
 {
   protected $container;
-  protected $token;
-  protected $data;
+  protected $requestDebugData;
   protected $collectors;
   protected $response;
+  protected $lifetime;
 
-  public function __construct(ContainerInterface $container)
+  public function __construct(ContainerInterface $container, $lifetime = 86400)
   {
     $this->container = $container;
-    $this->token = uniqid();
+    $this->lifetime = $lifetime;
+    $this->requestDebugData = new RequestDebugData(uniqid(), $this->container->getParameter('kernel.cache_dir').'/debug.db');
     $this->collectors = $this->initCollectors();
   }
 
@@ -41,6 +43,31 @@ class DataCollectorManager
     $this->container->getEventDispatcherService()->connect('core.response', array($this, 'handle'));
   }
 
+  public function handle(Event $event, Response $response)
+  {
+    if (!$event->getParameter('main_request'))
+    {
+      return $response;
+    }
+
+    $this->response = $response;
+
+    $data = array();
+    foreach ($this->collectors as $name => $collector)
+    {
+      $data[$name] = $collector->getData();
+    }
+    $this->requestDebugData->write($data);
+    $this->requestDebugData->purge($this->lifetime);
+
+    return $response;
+  }
+
+  public function getRequestDebugData()
+  {
+    return $this->requestDebugData;
+  }
+
   public function getResponse()
   {
     return $this->response;
@@ -74,36 +101,4 @@ class DataCollectorManager
 
     return $this->collectors = array_merge($coreColectors, $userCollectors);
   }
-
-  public function getData($name = null)
-  {
-    if (null === $name)
-    {
-      return $this->data;
-    }
-
-    return isset($this->data[$name]) ? $this->data[$name] : null;
-  }
-
-  public function handle(Event $event, Response $response)
-  {
-    if (!$event->getParameter('main_request'))
-    {
-      return $response;
-    }
-
-    $this->response = $response;
-
-    foreach ($this->collectors as $name => $collector)
-    {
-      $this->data[$name] = $collector->collect();
-    }
-
-    return $response;
-  }
-
-  public function getToken()
-  {
-    return $this->token;
-  }
 }

+ 2 - 4
src/Symfony/Framework/WebBundle/Debug/DataCollector/MemoryDataCollector.php

@@ -19,11 +19,9 @@ namespace Symfony\Framework\WebBundle\Debug\DataCollector;
  */
 class MemoryDataCollector extends DataCollector
 {
-  protected $data;
-
-  public function collect()
+  protected function collect()
   {
-    return $this->data = array(
+    return array(
       'memory' => memory_get_peak_usage(true),
     );
   }

+ 2 - 4
src/Symfony/Framework/WebBundle/Debug/DataCollector/TimerDataCollector.php

@@ -19,11 +19,9 @@ namespace Symfony\Framework\WebBundle\Debug\DataCollector;
  */
 class TimerDataCollector extends DataCollector
 {
-  protected $data;
-
-  public function collect()
+  protected function collect()
   {
-    return $this->data = array(
+    return array(
       'time' => microtime(true) - $this->container->getKernelService()->getStartTime(),
     );
   }

+ 86 - 0
src/Symfony/Framework/WebBundle/Debug/RequestDebugData.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace Symfony\Framework\WebBundle\Debug;
+
+/*
+ * This file is part of the symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * 
+ *
+ * @package    symfony
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class RequestDebugData
+{
+  protected $token;
+  protected $data;
+  protected $store;
+
+  public function __construct($token, $store)
+  {
+    $this->token = $token;
+    $this->store = $store;
+    $this->data = null;
+  }
+
+  public function hasData()
+  {
+    return null !== $this->data;
+  }
+
+  public function getData($name = null)
+  {
+    if (null === $this->data)
+    {
+      $this->data = $this->read();
+    }
+
+    if (null === $name)
+    {
+      return $this->data;
+    }
+
+    return isset($this->data[$name]) ? $this->data[$name] : null;
+  }
+
+  public function getToken()
+  {
+    return $this->token;
+  }
+
+  protected function read()
+  {
+    $db = $this->initDb(SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READ);
+    $this->data = $db->querySingle(sprintf("SELECT data FROM data WHERE token = '%s' LIMIT 1 ORDER BY created_at DESC", $db->escapeString($this->token)));
+    $db->close();
+  }
+
+  public function write($data)
+  {
+    $db = $this->initDb(SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
+    $db->exec(sprintf("INSERT INTO data (token, data, created_at) VALUES ('%s', '%s', %s)", $db->escapeString($this->token), $db->escapeString(serialize($data)), time()));
+    $db->close();
+  }
+
+  protected function initDb($flags)
+  {
+    $db = new \SQLite3($this->store, $flags);
+    $db->exec('CREATE TABLE IF NOT EXISTS data (token STRING, data STRING, created_at TIMESTAMP)');
+    $db->exec('CREATE INDEX IF NOT EXISTS data_data ON data (created_at)');
+
+    return $db;
+  }
+
+  public function purge($lifetime)
+  {
+    $db = $this->initDb(SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
+    $db->exec(sprintf("DELETE FROM data WHERE strftime('%%s', 'now') - created_at > %d", $lifetime));
+  }
+}

+ 2 - 0
src/Symfony/Framework/WebBundle/Resources/config/debug_data_collector.xml

@@ -6,6 +6,7 @@
 
   <parameters>
     <parameter key="debug.data_collector_manager.class">Symfony\Framework\WebBundle\Debug\DataCollector\DataCollectorManager</parameter>
+    <parameter key="debug.data_collector_manager.lifetime">86400</parameter>
     <parameter key="debug.data_collector.config.class">Symfony\Framework\WebBundle\Debug\DataCollector\ConfigDataCollector</parameter>
     <parameter key="debug.data_collector.app.class">Symfony\Framework\WebBundle\Debug\DataCollector\AppDataCollector</parameter>
     <parameter key="debug.data_collector.timer.class">Symfony\Framework\WebBundle\Debug\DataCollector\TimerDataCollector</parameter>
@@ -16,6 +17,7 @@
     <service id="debug.data_collector_manager" class="%debug.data_collector_manager.class%">
       <annotation name="kernel.listener" event="core.response" method="handle" />
       <argument type="service" id="service_container" />
+      <argument>%debug.data_collector_manager.lifetime%</argument>
     </service>
 
     <service id="debug.data_collector.config" class="%debug.data_collector.config.class%">