app/Service/EventSubscriber/MainRequestProfileSubscriber.php line 46

Open in your IDE?
  1. <?php
  2. namespace Sq\Service\EventSubscriber;
  3. use Sq\Entity\Profiler\Profile;
  4. use Sq\Event\Kernel\InitialiseContainerEvent;
  5. use Sq\Service\Profiler\ProfilerInterface;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Symfony\Component\HttpKernel\Event;
  8. use Symfony\Component\HttpKernel\KernelEvents;
  9. class MainRequestProfileSubscriber implements EventSubscriberInterface
  10. {
  11.     /** @var \Sq\Service\Profiler\ProfilerInterface */
  12.     private $profiler;
  13.     /** @var \Sq\Entity\Profiler\ProfileInterface */
  14.     private $mainProfile;
  15.     /**
  16.      * @param \Sq\Service\Profiler\ProfilerInterface $profiler
  17.      */
  18.     public function __construct(ProfilerInterface $profiler)
  19.     {
  20.         $this->profiler $profiler;
  21.     }
  22.     /** @inheritDoc */
  23.     public static function getSubscribedEvents()
  24.     {
  25.         return [
  26.             InitialiseContainerEvent::class => ['onInitializeContainer'],
  27.             // For the request and controller events, set the priority really low so that they are executed after the
  28.             // route and controller information has been calculated by first-party Symfony event listeners/subscribers.
  29.             KernelEvents::REQUEST => ['onRequest', -64],
  30.             KernelEvents::CONTROLLER => ['onController', -64],
  31.             KernelEvents::TERMINATE => ['onTerminate'],
  32.         ];
  33.     }
  34.     /**
  35.      * Start profiling the "main" application as soon as the container has been initialized.
  36.      *
  37.      * @param \Sq\Event\Kernel\InitialiseContainerEvent $event
  38.      */
  39.     public function onInitializeContainer(InitialiseContainerEvent $event): void
  40.     {
  41.         $this->mainProfile $this->profiler->start('main');
  42.     }
  43.     /**
  44.      * When the route has been determined, add that and information about the request to the main profile.
  45.      *
  46.      * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
  47.      */
  48.     public function onRequest(Event\RequestEvent $event): void
  49.     {
  50.         if ($this->mainProfile !== null)
  51.         {
  52.             $request $event->getRequest();
  53.             $clientFrontendVersion $request->headers->get('Client-Frontend-Version');
  54.             $this->mainProfile instanceof Profile && $this->mainProfile->setRequest($request);
  55.             $httpRequestStart $request->headers->get('X-Request-Start');
  56.             $phpRequestStartMs $request->attributes->get('request_start_ms');
  57.             $this->mainProfile->addDataField('request_method'$request->getMethod());
  58.             $this->mainProfile->addDataField('request_uri'$request->getPathInfo());
  59.             $this->mainProfile->addDataField('query_string'$request->getQueryString() ?? "");
  60.             $this->mainProfile->addDataField('route_name'$request->attributes->get('_route'''));
  61.             $this->mainProfile->addDataField('route_params'json_encode($request->attributes->get('_route_params', [])));
  62.             if (is_string($clientFrontendVersion) && $clientFrontendVersion !== '')
  63.             {
  64.                 $this->mainProfile->addDataField('client_frontend_version'$clientFrontendVersion);
  65.             }
  66.             if (is_string($httpRequestStart) && preg_match('/^t=(\d+)$/'$httpRequestStart$httpRequestStartMatches) === 1)
  67.             {
  68.                 $this->mainProfile->addDataField('http_request_start_ms', (int) round(((int) $httpRequestStartMatches[1]) / 1000));
  69.             }
  70.             if (is_numeric($phpRequestStartMs))
  71.             {
  72.                 $this->mainProfile->addDataField('php_request_start_ms', (int) $phpRequestStartMs);
  73.             }
  74.             if (isset($httpRequestStartMatches[1]) && is_numeric($phpRequestStartMs))
  75.             {
  76.                 $this->mainProfile->addDataField(
  77.                     'php_request_start_delay_ms',
  78.                     max(0, (int) $phpRequestStartMs - (int) round(((int) $httpRequestStartMatches[1]) / 1000))
  79.                 );
  80.             }
  81.         }
  82.     }
  83.     /**
  84.      * When the controller has been determined, add that information to the main profile.
  85.      *
  86.      * @param \Symfony\Component\HttpKernel\Event\ControllerEvent $event
  87.      */
  88.     public function onController(Event\ControllerEvent $event): void
  89.     {
  90.         if ($this->mainProfile !== null)
  91.         {
  92.             $request $event->getRequest();
  93.             $this->mainProfile->addDataField('controller'$request->attributes->get('_controller'''));
  94.         }
  95.     }
  96.     /**
  97.      * Stop profiling when the kernel terminates, instead of when the PHP script ends, for accuracy.
  98.      *
  99.      * @param \Symfony\Component\HttpKernel\Event\TerminateEvent $event
  100.      */
  101.     public function onTerminate(Event\TerminateEvent $event): void
  102.     {
  103.         if ($this->mainProfile !== null)
  104.         {
  105.             $this->mainProfile->stop();
  106.         }
  107.     }
  108. }