MessengerDataCollector.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Messenger\DataCollector;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\HttpKernel\DataCollector\DataCollector;
  14. use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
  15. use Symfony\Component\Messenger\TraceableMessageBus;
  16. use Symfony\Component\VarDumper\Caster\ClassStub;
  17. /**
  18. * @author Samuel Roze <samuel.roze@gmail.com>
  19. *
  20. * @final
  21. */
  22. class MessengerDataCollector extends DataCollector implements LateDataCollectorInterface
  23. {
  24. private $traceableBuses = [];
  25. public function registerBus(string $name, TraceableMessageBus $bus)
  26. {
  27. $this->traceableBuses[$name] = $bus;
  28. }
  29. /**
  30. * {@inheritdoc}
  31. */
  32. public function collect(Request $request, Response $response, \Throwable $exception = null)
  33. {
  34. // Noop. Everything is collected live by the traceable buses & cloned as late as possible.
  35. }
  36. /**
  37. * {@inheritdoc}
  38. */
  39. public function lateCollect()
  40. {
  41. $this->data = ['messages' => [], 'buses' => array_keys($this->traceableBuses)];
  42. $messages = [];
  43. foreach ($this->traceableBuses as $busName => $bus) {
  44. foreach ($bus->getDispatchedMessages() as $message) {
  45. $debugRepresentation = $this->cloneVar($this->collectMessage($busName, $message));
  46. $messages[] = [$debugRepresentation, $message['callTime']];
  47. }
  48. }
  49. // Order by call time
  50. usort($messages, function ($a, $b) { return $a[1] <=> $b[1]; });
  51. // Keep the messages clones only
  52. $this->data['messages'] = array_column($messages, 0);
  53. }
  54. /**
  55. * {@inheritdoc}
  56. */
  57. public function getName()
  58. {
  59. return 'messenger';
  60. }
  61. /**
  62. * {@inheritdoc}
  63. */
  64. public function reset()
  65. {
  66. $this->data = [];
  67. foreach ($this->traceableBuses as $traceableBus) {
  68. $traceableBus->reset();
  69. }
  70. }
  71. /**
  72. * {@inheritdoc}
  73. */
  74. protected function getCasters()
  75. {
  76. $casters = parent::getCasters();
  77. // Unset the default caster truncating collectors data.
  78. unset($casters['*']);
  79. return $casters;
  80. }
  81. private function collectMessage(string $busName, array $tracedMessage)
  82. {
  83. $message = $tracedMessage['message'];
  84. $debugRepresentation = [
  85. 'bus' => $busName,
  86. 'stamps' => $tracedMessage['stamps'] ?? null,
  87. 'stamps_after_dispatch' => $tracedMessage['stamps_after_dispatch'] ?? null,
  88. 'message' => [
  89. 'type' => new ClassStub(\get_class($message)),
  90. 'value' => $message,
  91. ],
  92. 'caller' => $tracedMessage['caller'],
  93. ];
  94. if (isset($tracedMessage['exception'])) {
  95. $exception = $tracedMessage['exception'];
  96. $debugRepresentation['exception'] = [
  97. 'type' => \get_class($exception),
  98. 'value' => $exception,
  99. ];
  100. }
  101. return $debugRepresentation;
  102. }
  103. public function getExceptionsCount(string $bus = null): int
  104. {
  105. $count = 0;
  106. foreach ($this->getMessages($bus) as $message) {
  107. $count += (int) isset($message['exception']);
  108. }
  109. return $count;
  110. }
  111. public function getMessages(string $bus = null): array
  112. {
  113. if (null === $bus) {
  114. return $this->data['messages'];
  115. }
  116. return array_filter($this->data['messages'], function ($message) use ($bus) {
  117. return $bus === $message['bus'];
  118. });
  119. }
  120. public function getBuses(): array
  121. {
  122. return $this->data['buses'];
  123. }
  124. }