vendor/sentry/sentry-symfony/src/EventListener/TracingConsoleListener.php line 85

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sentry\SentryBundle\EventListener;
  4. use Sentry\State\HubInterface;
  5. use Sentry\Tracing\Span;
  6. use Sentry\Tracing\SpanContext;
  7. use Sentry\Tracing\Transaction;
  8. use Sentry\Tracing\TransactionContext;
  9. use Sentry\Tracing\TransactionSource;
  10. use Symfony\Component\Console\Command\Command;
  11. use Symfony\Component\Console\Event\ConsoleCommandEvent;
  12. use Symfony\Component\Console\Event\ConsoleTerminateEvent;
  13. /**
  14. * This listener either starts a {@see Transaction} or a child {@see Span} when
  15. * a console command is executed to allow measuring the application performances.
  16. */
  17. final class TracingConsoleListener
  18. {
  19. /**
  20. * @var HubInterface The current hub
  21. */
  22. private $hub;
  23. /**
  24. * @var string[] The list of commands for which distributed tracing must be skipped
  25. */
  26. private $excludedCommands;
  27. /**
  28. * Constructor.
  29. *
  30. * @param HubInterface $hub The current hub
  31. * @param string[] $excludedCommands The list of commands for which distributed tracing must be skipped
  32. */
  33. public function __construct(HubInterface $hub, array $excludedCommands = [])
  34. {
  35. $this->hub = $hub;
  36. $this->excludedCommands = $excludedCommands;
  37. }
  38. /**
  39. * Handles the execution of a console command by starting a new {@see Transaction}
  40. * if it doesn't exists, or a child {@see Span} if it does.
  41. *
  42. * @param ConsoleCommandEvent $event The event
  43. */
  44. public function handleConsoleCommandEvent(ConsoleCommandEvent $event): void
  45. {
  46. $command = $event->getCommand();
  47. if ($this->isCommandExcluded($command)) {
  48. return;
  49. }
  50. $currentSpan = $this->hub->getSpan();
  51. if (null === $currentSpan) {
  52. $transactionContext = new TransactionContext();
  53. $transactionContext->setOp('console.command');
  54. $transactionContext->setName($this->getSpanName($command));
  55. $transactionContext->setSource(TransactionSource::task());
  56. $span = $this->hub->startTransaction($transactionContext);
  57. } else {
  58. $spanContext = new SpanContext();
  59. $spanContext->setOp('console.command');
  60. $spanContext->setDescription($this->getSpanName($command));
  61. $span = $currentSpan->startChild($spanContext);
  62. }
  63. $this->hub->setSpan($span);
  64. }
  65. /**
  66. * Handles the termination of a console command by stopping the active {@see Span}
  67. * or {@see Transaction}.
  68. *
  69. * @param ConsoleTerminateEvent $event The event
  70. */
  71. public function handleConsoleTerminateEvent(ConsoleTerminateEvent $event): void
  72. {
  73. if ($this->isCommandExcluded($event->getCommand())) {
  74. return;
  75. }
  76. $span = $this->hub->getSpan();
  77. if (null !== $span) {
  78. $span->finish();
  79. }
  80. }
  81. private function getSpanName(?Command $command): string
  82. {
  83. if (null === $command || null === $command->getName()) {
  84. return '<unnamed command>';
  85. }
  86. return $command->getName();
  87. }
  88. private function isCommandExcluded(?Command $command): bool
  89. {
  90. if (null === $command) {
  91. return true;
  92. }
  93. return \in_array($command->getName(), $this->excludedCommands, true);
  94. }
  95. }