[Messenger] Improve the profiler panel
This commit is contained in:
parent
64a4a2b47f
commit
3d19578297
@ -4,17 +4,33 @@
|
||||
|
||||
{% block toolbar %}
|
||||
{% if collector.messages|length > 0 %}
|
||||
{% set status_color = collector.exceptionsCount ? 'red' %}
|
||||
{% set icon %}
|
||||
{{ include('@WebProfiler/Icon/messenger.svg') }}
|
||||
<span class="sf-toolbar-value">{{ collector.messages|length }}</span>
|
||||
{% endset %}
|
||||
|
||||
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: 'messenger' }) }}
|
||||
{% set text %}
|
||||
{% for bus in collector.buses %}
|
||||
{% set exceptionsCount = collector.exceptionsCount(bus) %}
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>{{ bus }}</b>
|
||||
<span
|
||||
title="{{ exceptionsCount }} message(s) with exceptions"
|
||||
class="sf-toolbar-status sf-toolbar-status-{{ exceptionsCount ? 'red' }}"
|
||||
>
|
||||
{{ collector.messages(bus)|length }}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endset %}
|
||||
|
||||
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: 'messenger', status: status_color }) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
<span class="label">
|
||||
<span class="label {{ collector.exceptionsCount ? 'label-status-error' }}">
|
||||
<span class="icon">{{ include('@WebProfiler/Icon/messenger.svg') }}</span>
|
||||
<strong>Messages</strong>
|
||||
|
||||
@ -24,7 +40,28 @@
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ parent() }}
|
||||
<style>
|
||||
.message-item thead th { position: relative; cursor: pointer; user-select: none; padding-right: 35px; }
|
||||
.message-item tbody tr td:first-child { width: 115px; }
|
||||
|
||||
.message-item .label { float: right; padding: 1px 5px; opacity: .75; margin-left: 5px; }
|
||||
.message-item .toggle-button { position: absolute; right: 6px; top: 6px; opacity: .5; pointer-events: none }
|
||||
.message-item .icon svg { height: 24px; width: 24px; }
|
||||
|
||||
.message-item .sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; }
|
||||
.message-item .sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; }
|
||||
|
||||
.message-bus .badge.status-some-errors { line-height: 16px; border-bottom: 2px solid #B0413E; }
|
||||
|
||||
.message-item .sf-toggle-content.sf-toggle-visible { display: table-row-group; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block panel %}
|
||||
{% import _self as helper %}
|
||||
|
||||
<h2>Messages</h2>
|
||||
|
||||
{% if collector.messages is empty %}
|
||||
@ -32,41 +69,99 @@
|
||||
<p>No messages have been collected.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bus</th>
|
||||
<th>Message</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for message in collector.messages %}
|
||||
<tr>
|
||||
<td>{{ message.bus }}</td>
|
||||
<td>
|
||||
{% if message.result.object is defined %}
|
||||
{{ profiler_dump(message.message.object, maxDepth=2) }}
|
||||
{% else %}
|
||||
{{ message.message.type }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if message.result.object is defined %}
|
||||
{{ profiler_dump(message.result.object, maxDepth=2) }}
|
||||
{% elseif message.result.type is defined %}
|
||||
{{ message.result.type }}
|
||||
{% if message.result.value is defined %}
|
||||
{{ message.result.value }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if message.exception.type is defined %}
|
||||
{{ message.exception.type }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="sf-tabs message-bus">
|
||||
<div class="tab">
|
||||
{% set messages = collector.messages %}
|
||||
{% set exceptionsCount = collector.exceptionsCount %}
|
||||
<h3 class="tab-title">All<span class="badge {{ exceptionsCount ? exceptionsCount == messages|length ? 'status-error' : 'status-some-errors' }}">{{ messages|length }}</span></h3>
|
||||
|
||||
<div class="tab-content">
|
||||
<p class="text-muted">Ordered list of dispatched messages across all your buses</p>
|
||||
{{ helper.render_bus_messages(messages, true) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for bus in collector.buses %}
|
||||
<div class="tab message-bus">
|
||||
{% set messages = collector.messages(bus) %}
|
||||
{% set exceptionsCount = collector.exceptionsCount(bus) %}
|
||||
<h3 class="tab-title">{{ bus }}<span class="badge {{ exceptionsCount ? exceptionsCount == messages|length ? 'status-error' : 'status-some-errors' }}">{{ messages|length }}</span></h3>
|
||||
|
||||
<div class="tab-content">
|
||||
<p class="text-muted">Ordered list of messages dispatched on the <code>{{ bus }}</code> bus</p>
|
||||
{{ helper.render_bus_messages(messages) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% macro render_bus_messages(messages, showBus = false) %}
|
||||
{% set discr = random() %}
|
||||
{% for i, dispatchCall in messages %}
|
||||
<table class="message-item">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2" class="sf-toggle"
|
||||
data-toggle-selector="#message-item-{{ discr }}-{{ i }}-details"
|
||||
data-toggle-initial="{{ loop.first ? 'display' }}"
|
||||
>
|
||||
<span class="dump-inline">{{ profiler_dump(dispatchCall.message.type) }}</span>
|
||||
{% if showBus %}
|
||||
<span class="label">{{ dispatchCall.bus }}</span>
|
||||
{% endif %}
|
||||
{% if dispatchCall.exception is defined %}
|
||||
<span class="label status-error">exception</span>
|
||||
{% endif %}
|
||||
<a class="toggle-button">
|
||||
<span class="icon icon-close">{{ include('@Twig/images/icon-minus-square.svg') }}</span>
|
||||
<span class="icon icon-open">{{ include('@Twig/images/icon-plus-square.svg') }}</span>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="message-item-{{ discr }}-{{ i }}-details" class="sf-toggle-content">
|
||||
{% if showBus %}
|
||||
<tr>
|
||||
<td class="text-bold">Bus</td>
|
||||
<td>{{ dispatchCall.bus }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td class="text-bold">Message</td>
|
||||
<td>{{ profiler_dump(dispatchCall.message.value, maxDepth=2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-bold">Envelope items</td>
|
||||
<td>
|
||||
{% for item in dispatchCall.envelopeItems %}
|
||||
{{ profiler_dump(item) }}
|
||||
{% else %}
|
||||
<span class="text-muted">No items</span>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-bold">Result</td>
|
||||
<td>
|
||||
{% if dispatchCall.result is defined %}
|
||||
{{ profiler_dump(dispatchCall.result.seek('value'), maxDepth=2) }}
|
||||
{% elseif dispatchCall.exception is defined %}
|
||||
<span class="text-danger">No result as an exception occurred</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if dispatchCall.exception is defined %}
|
||||
<tr>
|
||||
<td class="text-bold">Exception</td>
|
||||
<td>
|
||||
{{ profiler_dump(dispatchCall.exception.value, maxDepth=1) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
@ -215,6 +215,9 @@ table tbody ul {
|
||||
.text-muted {
|
||||
color: #999;
|
||||
}
|
||||
.text-danger {
|
||||
color: {{ colors.error|raw }};
|
||||
}
|
||||
.text-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Symfony\Component\Messenger\TraceableMessageBus;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
/**
|
||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||
@ -44,13 +46,25 @@ class MessengerDataCollector extends DataCollector implements LateDataCollectorI
|
||||
*/
|
||||
public function lateCollect()
|
||||
{
|
||||
$this->data = array('messages' => array());
|
||||
$this->data = array('messages' => array(), 'buses' => array_keys($this->traceableBuses));
|
||||
|
||||
$messages = array();
|
||||
foreach ($this->traceableBuses as $busName => $bus) {
|
||||
foreach ($bus->getDispatchedMessages() as $message) {
|
||||
$this->data['messages'][] = $this->collectMessage($busName, $message);
|
||||
$debugRepresentation = $this->cloneVar($this->collectMessage($busName, $message));
|
||||
$messages[] = array($debugRepresentation, $message['callTime']);
|
||||
}
|
||||
}
|
||||
|
||||
// Order by call time
|
||||
usort($messages, function (array $a, array $b): int {
|
||||
return $a[1] > $b[1] ? 1 : -1;
|
||||
});
|
||||
|
||||
// Keep the messages clones only
|
||||
$this->data['messages'] = array_map(function (array $item): Data {
|
||||
return $item[0];
|
||||
}, $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,31 +92,19 @@ class MessengerDataCollector extends DataCollector implements LateDataCollectorI
|
||||
|
||||
$debugRepresentation = array(
|
||||
'bus' => $busName,
|
||||
'envelopeItems' => $tracedMessage['envelopeItems'] ?? null,
|
||||
'message' => array(
|
||||
'type' => \get_class($message),
|
||||
'object' => $this->cloneVar($message),
|
||||
'type' => new ClassStub(\get_class($message)),
|
||||
'value' => $message,
|
||||
),
|
||||
);
|
||||
|
||||
if (array_key_exists('result', $tracedMessage)) {
|
||||
$result = $tracedMessage['result'];
|
||||
|
||||
if (\is_object($result)) {
|
||||
$debugRepresentation['result'] = array(
|
||||
'type' => \get_class($result),
|
||||
'object' => $this->cloneVar($result),
|
||||
);
|
||||
} elseif (\is_array($result)) {
|
||||
$debugRepresentation['result'] = array(
|
||||
'type' => 'array',
|
||||
'object' => $this->cloneVar($result),
|
||||
);
|
||||
} else {
|
||||
$debugRepresentation['result'] = array(
|
||||
'type' => \gettype($result),
|
||||
'value' => $result,
|
||||
);
|
||||
}
|
||||
$debugRepresentation['result'] = array(
|
||||
'type' => \is_object($result) ? \get_class($result) : gettype($result),
|
||||
'value' => $result,
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($tracedMessage['exception'])) {
|
||||
@ -110,15 +112,31 @@ class MessengerDataCollector extends DataCollector implements LateDataCollectorI
|
||||
|
||||
$debugRepresentation['exception'] = array(
|
||||
'type' => \get_class($exception),
|
||||
'message' => $exception->getMessage(),
|
||||
'value' => $exception,
|
||||
);
|
||||
}
|
||||
|
||||
return $debugRepresentation;
|
||||
}
|
||||
|
||||
public function getMessages(): array
|
||||
public function getExceptionsCount(string $bus = null): int
|
||||
{
|
||||
return $this->data['messages'] ?? array();
|
||||
return array_reduce($this->getMessages($bus), function (int $carry, Data $message) {
|
||||
return $carry += isset($message['exception']) ? 1 : 0;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public function getMessages(string $bus = null): array
|
||||
{
|
||||
$messages = $this->data['messages'] ?? array();
|
||||
|
||||
return $bus ? array_filter($messages, function (Data $message) use ($bus): bool {
|
||||
return $bus === $message['bus'];
|
||||
}) : $messages;
|
||||
}
|
||||
|
||||
public function getBuses(): array
|
||||
{
|
||||
return $this->data['buses'];
|
||||
}
|
||||
}
|
||||
|
@ -16,14 +16,22 @@ use Symfony\Component\Messenger\DataCollector\MessengerDataCollector;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
|
||||
use Symfony\Component\Messenger\TraceableMessageBus;
|
||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
|
||||
/**
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class MessengerDataCollectorTest extends TestCase
|
||||
{
|
||||
use VarDumperTestTrait;
|
||||
/** @var CliDumper */
|
||||
private $dumper;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->dumper = new CliDumper();
|
||||
$this->dumper->setColors(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getHandleTestData
|
||||
@ -46,17 +54,18 @@ class MessengerDataCollectorTest extends TestCase
|
||||
$messages = $collector->getMessages();
|
||||
$this->assertCount(1, $messages);
|
||||
|
||||
$this->assertDumpMatchesFormat($expected, $messages[0]);
|
||||
$this->assertStringMatchesFormat($expected, $this->getDataAsString($messages[0]));
|
||||
}
|
||||
|
||||
public function getHandleTestData()
|
||||
{
|
||||
$messageDump = <<<DUMP
|
||||
"bus" => "default"
|
||||
"envelopeItems" => null
|
||||
"message" => array:2 [
|
||||
"type" => "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"
|
||||
"object" => Symfony\Component\VarDumper\Cloner\Data {%A
|
||||
%A+class: "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"%A
|
||||
"value" => Symfony\Component\Messenger\Tests\Fixtures\DummyMessage %A
|
||||
-message: "dummy message"
|
||||
}
|
||||
]
|
||||
DUMP;
|
||||
@ -64,7 +73,7 @@ DUMP;
|
||||
yield 'no returned value' => array(
|
||||
null,
|
||||
<<<DUMP
|
||||
array:3 [
|
||||
array:4 [
|
||||
$messageDump
|
||||
"result" => array:2 [
|
||||
"type" => "NULL"
|
||||
@ -77,7 +86,7 @@ DUMP
|
||||
yield 'scalar returned value' => array(
|
||||
'returned value',
|
||||
<<<DUMP
|
||||
array:3 [
|
||||
array:4 [
|
||||
$messageDump
|
||||
"result" => array:2 [
|
||||
"type" => "string"
|
||||
@ -90,11 +99,13 @@ DUMP
|
||||
yield 'array returned value' => array(
|
||||
array('returned value'),
|
||||
<<<DUMP
|
||||
array:3 [
|
||||
array:4 [
|
||||
$messageDump
|
||||
"result" => array:2 [
|
||||
"type" => "array"
|
||||
"object" => Symfony\Component\VarDumper\Cloner\Data {%A
|
||||
"value" => array:1 [
|
||||
0 => "returned value"
|
||||
]
|
||||
]
|
||||
]
|
||||
DUMP
|
||||
@ -123,21 +134,66 @@ DUMP
|
||||
$messages = $collector->getMessages();
|
||||
$this->assertCount(1, $messages);
|
||||
|
||||
$this->assertDumpMatchesFormat(<<<DUMP
|
||||
array:3 [
|
||||
$this->assertStringMatchesFormat(<<<DUMP
|
||||
array:4 [
|
||||
"bus" => "default"
|
||||
"envelopeItems" => null
|
||||
"message" => array:2 [
|
||||
"type" => "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"
|
||||
"object" => Symfony\Component\VarDumper\Cloner\Data {%A
|
||||
%A+class: "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"%A
|
||||
"value" => Symfony\Component\Messenger\Tests\Fixtures\DummyMessage %A
|
||||
-message: "dummy message"
|
||||
}
|
||||
]
|
||||
"exception" => array:2 [
|
||||
"type" => "RuntimeException"
|
||||
"message" => "foo"
|
||||
"value" => RuntimeException %A
|
||||
]
|
||||
]
|
||||
]
|
||||
DUMP
|
||||
, $messages[0]);
|
||||
, $this->getDataAsString($messages[0]));
|
||||
}
|
||||
|
||||
public function testKeepsOrderedDispatchCalls()
|
||||
{
|
||||
$firstBus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$firstBus = new TraceableMessageBus($firstBus);
|
||||
|
||||
$secondBus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$secondBus = new TraceableMessageBus($secondBus);
|
||||
|
||||
$collector = new MessengerDataCollector();
|
||||
$collector->registerBus('first bus', $firstBus);
|
||||
$collector->registerBus('second bus', $secondBus);
|
||||
|
||||
$firstBus->dispatch(new DummyMessage('#1'));
|
||||
$secondBus->dispatch(new DummyMessage('#2'));
|
||||
$secondBus->dispatch(new DummyMessage('#3'));
|
||||
$firstBus->dispatch(new DummyMessage('#4'));
|
||||
$secondBus->dispatch(new DummyMessage('#5'));
|
||||
|
||||
$collector->lateCollect();
|
||||
|
||||
$messages = $collector->getMessages();
|
||||
$this->assertCount(5, $messages);
|
||||
|
||||
$this->assertSame('#1', $messages[0]['message']['value']['message']);
|
||||
$this->assertSame('first bus', $messages[0]['bus']);
|
||||
|
||||
$this->assertSame('#2', $messages[1]['message']['value']['message']);
|
||||
$this->assertSame('second bus', $messages[1]['bus']);
|
||||
|
||||
$this->assertSame('#3', $messages[2]['message']['value']['message']);
|
||||
$this->assertSame('second bus', $messages[2]['bus']);
|
||||
|
||||
$this->assertSame('#4', $messages[3]['message']['value']['message']);
|
||||
$this->assertSame('first bus', $messages[3]['bus']);
|
||||
|
||||
$this->assertSame('#5', $messages[4]['message']['value']['message']);
|
||||
$this->assertSame('second bus', $messages[4]['bus']);
|
||||
}
|
||||
|
||||
private function getDataAsString(Data $data): string
|
||||
{
|
||||
return rtrim($this->dumper->dump($data, true));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Messenger\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\Messenger\EnvelopeItemInterface;
|
||||
|
||||
class AnEnvelopeItem implements EnvelopeItemInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Asynchronous\Transport\ReceivedMessage;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\EnvelopeAwareInterface;
|
||||
use Symfony\Component\Messenger\EnvelopeItemInterface;
|
||||
use Symfony\Component\Messenger\MessageBus;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeItem;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
|
||||
|
||||
class MessageBusTest extends TestCase
|
||||
@ -160,22 +160,3 @@ class MessageBusTest extends TestCase
|
||||
$bus->dispatch($envelope);
|
||||
}
|
||||
}
|
||||
|
||||
class AnEnvelopeItem implements EnvelopeItemInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Messenger\Tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeItem;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
|
||||
use Symfony\Component\Messenger\TraceableMessageBus;
|
||||
|
||||
@ -28,19 +29,29 @@ class TraceableMessageBusTest extends TestCase
|
||||
|
||||
$traceableBus = new TraceableMessageBus($bus);
|
||||
$this->assertSame($result, $traceableBus->dispatch($message));
|
||||
$this->assertSame(array(array('message' => $message, 'result' => $result)), $traceableBus->getDispatchedMessages());
|
||||
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
|
||||
$this->assertArraySubset(array(
|
||||
'message' => $message,
|
||||
'result' => $result,
|
||||
'envelopeItems' => null,
|
||||
), $tracedMessages[0], true);
|
||||
}
|
||||
|
||||
public function testItTracesResultWithEnvelope()
|
||||
{
|
||||
$envelope = Envelope::wrap($message = new DummyMessage('Hello'));
|
||||
$envelope = Envelope::wrap($message = new DummyMessage('Hello'))->with($envelopeItem = new AnEnvelopeItem());
|
||||
|
||||
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$bus->expects($this->once())->method('dispatch')->with($envelope)->willReturn($result = array('foo' => 'bar'));
|
||||
|
||||
$traceableBus = new TraceableMessageBus($bus);
|
||||
$this->assertSame($result, $traceableBus->dispatch($envelope));
|
||||
$this->assertSame(array(array('message' => $message, 'result' => $result)), $traceableBus->getDispatchedMessages());
|
||||
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
|
||||
$this->assertArraySubset(array(
|
||||
'message' => $message,
|
||||
'result' => $result,
|
||||
'envelopeItems' => array($envelopeItem),
|
||||
), $tracedMessages[0], true);
|
||||
}
|
||||
|
||||
public function testItTracesExceptions()
|
||||
@ -58,6 +69,11 @@ class TraceableMessageBusTest extends TestCase
|
||||
$this->assertSame($exception, $e);
|
||||
}
|
||||
|
||||
$this->assertSame(array(array('message' => $message, 'exception' => $exception)), $traceableBus->getDispatchedMessages());
|
||||
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
|
||||
$this->assertArraySubset(array(
|
||||
'message' => $message,
|
||||
'exception' => $exception,
|
||||
'envelopeItems' => null,
|
||||
), $tracedMessages[0], true);
|
||||
}
|
||||
}
|
||||
|
@ -29,21 +29,27 @@ class TraceableMessageBus implements MessageBusInterface
|
||||
*/
|
||||
public function dispatch($message)
|
||||
{
|
||||
$callTime = microtime(true);
|
||||
$messageToTrace = $message instanceof Envelope ? $message->getMessage() : $message;
|
||||
$envelopeItems = $message instanceof Envelope ? array_values($message->all()) : null;
|
||||
|
||||
try {
|
||||
$result = $this->decoratedBus->dispatch($message);
|
||||
|
||||
$this->dispatchedMessages[] = array(
|
||||
'envelopeItems' => $envelopeItems,
|
||||
'message' => $messageToTrace,
|
||||
'result' => $result,
|
||||
'callTime' => $callTime,
|
||||
);
|
||||
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
$this->dispatchedMessages[] = array(
|
||||
'envelopeItems' => $envelopeItems,
|
||||
'message' => $messageToTrace,
|
||||
'exception' => $e,
|
||||
'callTime' => $callTime,
|
||||
);
|
||||
|
||||
throw $e;
|
||||
|
Reference in New Issue
Block a user