Display orphaned events in profiler

This commit is contained in:
Mateusz Sip 2017-10-01 22:31:12 +02:00 committed by Fabien Potencier
parent 07766b3905
commit 509f9a9233
11 changed files with 142 additions and 11 deletions

View File

@ -1,6 +1,11 @@
UPGRADE FROM 4.0 to 4.1 UPGRADE FROM 4.0 to 4.1
======================= =======================
EventDispatcher
---------------
* The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0.
HttpFoundation HttpFoundation
-------------- --------------

View File

@ -1,6 +1,11 @@
UPGRADE FROM 4.x to 5.0 UPGRADE FROM 4.x to 5.0
======================= =======================
EventDispatcher
---------------
* The `TraceableEventDispatcherInterface` has been removed.
HttpFoundation HttpFoundation
-------------- --------------

View File

@ -1,6 +1,11 @@
CHANGELOG CHANGELOG
========= =========
4.1.0
-----
* added information about orphaned events
4.0.0 4.0.0
----- -----

View File

@ -45,6 +45,26 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="tab">
<h3 class="tab-title">Orphaned events <span class="badge">{{ collector.orphanedEvents|length }}</span></h3>
<div class="tab-content">
{% if collector.orphanedEvents is empty %}
<div class="empty">
<p>
<strong>There are no orphaned events</strong>.
</p>
<p>
All dispatched events were handled or an error occurred
when trying to collect orphaned events (in which case check the
logs to get more information).
</p>
</div>
{% else %}
{{ helper.render_table(collector.orphanedEvents) }}
{% endif %}
</div>
</div>
</div> </div>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -1,6 +1,12 @@
CHANGELOG CHANGELOG
========= =========
4.1.0
-----
* The `TraceableEventDispatcher::getOrphanedEvents()` method has been added.
* The `TraceableEventDispatcherInterface` has been deprecated and will be removed in 5.0.
4.0.0 4.0.0
----- -----

View File

@ -32,6 +32,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
private $called; private $called;
private $dispatcher; private $dispatcher;
private $wrappedListeners; private $wrappedListeners;
private $orphanedEvents;
public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null)
{ {
@ -40,6 +41,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
$this->logger = $logger; $this->logger = $logger;
$this->called = array(); $this->called = array();
$this->wrappedListeners = array(); $this->wrappedListeners = array();
$this->orphanedEvents = array();
} }
/** /**
@ -207,6 +209,16 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
return $notCalled; return $notCalled;
} }
/**
* Gets the orphaned events.
*
* @return array An array of orphaned events
*/
public function getOrphanedEvents()
{
return $this->orphanedEvents;
}
public function reset() public function reset()
{ {
$this->called = array(); $this->called = array();
@ -247,6 +259,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
private function preProcess($eventName) private function preProcess($eventName)
{ {
if (!$this->dispatcher->hasListeners($eventName)) {
$this->orphanedEvents[] = $eventName;
return;
}
foreach ($this->dispatcher->getListeners($eventName) as $listener) { foreach ($this->dispatcher->getListeners($eventName) as $listener) {
$priority = $this->getListenerPriority($eventName, $listener); $priority = $this->getListenerPriority($eventName, $listener);
$wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this); $wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this);

View File

@ -14,6 +14,8 @@ namespace Symfony\Component\EventDispatcher\Debug;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* @deprecated since version 4.1, will be removed in 5.0.
*
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
interface TraceableEventDispatcherInterface extends EventDispatcherInterface interface TraceableEventDispatcherInterface extends EventDispatcherInterface

View File

@ -153,6 +153,40 @@ class TraceableEventDispatcherTest extends TestCase
$this->assertCount(2, $dispatcher->getCalledListeners()); $this->assertCount(2, $dispatcher->getCalledListeners());
} }
public function testItReturnsNoOrphanedEventsWhenCreated()
{
// GIVEN
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
// WHEN
$events = $tdispatcher->getOrphanedEvents();
// THEN
$this->assertEmpty($events);
}
public function testItReturnsOrphanedEventsAfterDispatch()
{
// GIVEN
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->dispatch('foo');
// WHEN
$events = $tdispatcher->getOrphanedEvents();
// THEN
$this->assertCount(1, $events);
$this->assertEquals(array('foo'), $events);
}
public function testItDoesNotReturnHandledEvents()
{
// GIVEN
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {});
$tdispatcher->dispatch('foo');
// WHEN
$events = $tdispatcher->getOrphanedEvents();
// THEN
$this->assertEmpty($events);
}
public function testLogger() public function testLogger()
{ {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();

View File

@ -4,6 +4,7 @@ CHANGELOG
4.1.0 4.1.0
----- -----
* added orphaned events support to `EventDataCollector`
* `ExceptionListener` now logs and collects exceptions at priority `2048` (previously logged at `-128` and collected at `0`) * `ExceptionListener` now logs and collects exceptions at priority `2048` (previously logged at `-128` and collected at `0`)
4.0.0 4.0.0

View File

@ -11,10 +11,11 @@
namespace Symfony\Component\HttpKernel\DataCollector; namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
/** /**
* EventDataCollector. * EventDataCollector.
@ -38,6 +39,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
$this->data = array( $this->data = array(
'called_listeners' => array(), 'called_listeners' => array(),
'not_called_listeners' => array(), 'not_called_listeners' => array(),
'orphaned_events' => array(),
); );
} }
@ -56,6 +58,11 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
$this->setCalledListeners($this->dispatcher->getCalledListeners()); $this->setCalledListeners($this->dispatcher->getCalledListeners());
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners()); $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
} }
if ($this->dispatcher instanceof TraceableEventDispatcher) {
$this->setOrphanedEvents($this->dispatcher->getOrphanedEvents());
}
$this->data = $this->cloneVar($this->data); $this->data = $this->cloneVar($this->data);
} }
@ -64,7 +71,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
* *
* @param array $listeners An array of called listeners * @param array $listeners An array of called listeners
* *
* @see TraceableEventDispatcherInterface * @see TraceableEventDispatcher
*/ */
public function setCalledListeners(array $listeners) public function setCalledListeners(array $listeners)
{ {
@ -76,7 +83,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
* *
* @return array An array of called listeners * @return array An array of called listeners
* *
* @see TraceableEventDispatcherInterface * @see TraceableEventDispatcher
*/ */
public function getCalledListeners() public function getCalledListeners()
{ {
@ -86,9 +93,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
/** /**
* Sets the not called listeners. * Sets the not called listeners.
* *
* @param array $listeners An array of not called listeners * @param array $listeners
* *
* @see TraceableEventDispatcherInterface * @see TraceableEventDispatcher
*/ */
public function setNotCalledListeners(array $listeners) public function setNotCalledListeners(array $listeners)
{ {
@ -98,15 +105,39 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
/** /**
* Gets the not called listeners. * Gets the not called listeners.
* *
* @return array An array of not called listeners * @return array
* *
* @see TraceableEventDispatcherInterface * @see TraceableEventDispatcher
*/ */
public function getNotCalledListeners() public function getNotCalledListeners()
{ {
return $this->data['not_called_listeners']; return $this->data['not_called_listeners'];
} }
/**
* Sets the orphaned events.
*
* @param array $events An array of orphaned events
*
* @see TraceableEventDispatcher
*/
public function setOrphanedEvents(array $events)
{
$this->data['orphaned_events'] = $events;
}
/**
* Gets the orphaned events.
*
* @return array An array of orphaned events
*
* @see TraceableEventDispatcher
*/
public function getOrphanedEvents()
{
return $this->data['orphaned_events'];
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -11,10 +11,9 @@
namespace Symfony\Component\HttpKernel\Tests\Fixtures; namespace Symfony\Component\HttpKernel\Tests\Fixtures;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcher;
class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface class TestEventDispatcher extends TraceableEventDispatcher
{ {
public function getCalledListeners() public function getCalledListeners()
{ {
@ -29,4 +28,9 @@ class TestEventDispatcher extends EventDispatcher implements TraceableEventDispa
public function reset() public function reset()
{ {
} }
public function getOrphanedEvents()
{
return array();
}
} }