Improved profiler to store and retrieve sub requests data

This commit is contained in:
noel guilbert 2011-02-26 17:24:02 +01:00
parent e16c666266
commit a8eff2b154
7 changed files with 122 additions and 10 deletions

View File

@ -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;

View File

@ -27,6 +27,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>%profiler_listener.only_exceptions%</argument>

View File

@ -76,4 +76,21 @@ Request
{% else %}
<em>No request session attributes</em>
{% 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 %}

View File

@ -295,6 +295,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.

View File

@ -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();

View File

@ -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.
*

View File

@ -56,7 +56,7 @@ class SqliteProfilerStorage 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;
@ -69,15 +69,28 @@ class SqliteProfilerStorage 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']);
} else {
return false;
}
}
/**
* {@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}
*/