Profiler

The profiler is a powerful development tool that gives detailed informationabout the execution of any request. Never enable the profiler in productionenvironments as it will lead to major security vulnerabilities in your project.

Installation

In applications using Symfony Flex, run this command toinstall the profiler Symfony pack before using it:

  1. $ composer require --dev symfony/profiler-pack

Now browse any page of your application in the development environment to letthe profiler collect information. Then, click on any element of the debugtoolbar injected at the bottom of your pages to open the web interface of theSymfony Profiler, which will look like this:

_images/web-interface.png

Accessing Profiling Data Programmatically

Most of the times, the profiler information is accessed and analyzed using itsweb-based interface. However, you can also retrieve profiling informationprogrammatically thanks to the methods provided by the profiler service.

When the response object is available, use theloadProfileFromResponse()method to access to its associated profile:

  1. // ... $profiler is the 'profiler' service
  2. $profile = $profiler->loadProfileFromResponse($response);

When the profiler stores data about a request, it also associates a token with it;this token is available in the X-Debug-Token HTTP header of the response.Using this token, you can access the profile of any past response thanks to theloadProfile() method:

  1. $token = $response->headers->get('X-Debug-Token');
  2. $profile = $profiler->loadProfile($token);

Tip

When the profiler is enabled but not the web debug toolbar, inspect the pagewith your browser's developer tools to get the value of the X-Debug-TokenHTTP header.

The profiler service also provides thefind() method tolook for tokens based on some criteria:

  1. // gets the latest 10 tokens
  2. $tokens = $profiler->find('', '', 10, '', '', '');
  3.  
  4. // gets the latest 10 tokens for all URL containing /admin/
  5. $tokens = $profiler->find('', '/admin/', 10, '', '', '');
  6.  
  7. // gets the latest 10 tokens for local POST requests
  8. $tokens = $profiler->find('127.0.0.1', '', 10, 'POST', '', '');
  9.  
  10. // gets the latest 10 tokens for requests that happened between 2 and 4 days ago
  11. $tokens = $profiler->find('', '', 10, '', '4 days ago', '2 days ago');

Data Collectors

The profiler gets its information using some services called "data collectors".Symfony comes with several collectors that get information about the request,the logger, the routing, the cache, etc.

Run this command to get the list of collectors actually enabled in your app:

  1. $ php bin/console debug:container --tag=data_collector

You can also create your own data collector tostore any data generated by your app and display it in the debug toolbar and theprofiler web interface.

Timing the Execution of the Application

If you want to measure the time some tasks take in your application, there's noneed to create a custom data collector. Instead, use the Stopwatch componentwhich provides utilities to profile code and displays the results on the"Performance" panel of the Profiler web interface.

When using autowiring, type-hint any argument withthe Stopwatch class and Symfony willinject the Stopwatch service. Then, use the start(), lap() andstop() methods to measure time:

  1. // a user signs up and the timer starts...
  2. $stopwatch->start('user-sign-up');
  3.  
  4. // ...do things to sign up the user...
  5. $stopwatch->lap('user-sign-up');
  6.  
  7. // ...the sign up process is finished
  8. $stopwatch->stop('user-sign-up');

Tip

Consider using a professional profiler such as Blackfire to measure andanalyze the execution of your application in detail.

Enabling the Profiler Conditionally

Caution

The possibility to use a matcher to enable the profiler conditionally wasremoved in Symfony 4.0.

Symfony Profiler cannot be enabled/disabled conditionally using matchers, becausethat feature was removed in Symfony 4.0. However, you can use the enable()and disable() methods of the Profilerclass in your controllers to manage the profiler programmatically:

  1. use Symfony\Component\HttpKernel\Profiler\Profiler;
  2. // ...
  3.  
  4. class DefaultController
  5. {
  6. // ...
  7.  
  8. public function someMethod(?Profiler $profiler)
  9. {
  10. // $profiler won't be set if your environment doesn't have the profiler (like prod, by default)
  11. if (null !== $profiler) {
  12. // if it exists, disable the profiler for this particular controller action
  13. $profiler->disable();
  14. }
  15.  
  16. // ...
  17. }
  18. }

In order for the profiler to be injected into your controller you need tocreate an alias pointing to the existing profiler service:

  • YAML
  1. # config/services_dev.yaml
  2. services:
  3. Symfony\Component\HttpKernel\Profiler\Profiler: '@profiler'
  • XML
  1. <!-- config/services_dev.xml -->
  2. <?xml version="1.0" encoding="UTF-8" ?>
  3. <container xmlns="http://symfony.com/schema/dic/services"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://symfony.com/schema/dic/services
  6. https://symfony.com/schema/dic/services/services-1.0.xsd">
  7.  
  8. <services>
  9. <service id="Symfony\Component\HttpKernel\Profiler\Profiler" alias="profiler"/>
  10. </services>
  11. </container>
  • PHP
  1. // config/services_dev.php
  2. use Symfony\Component\HttpKernel\Profiler\Profiler;
  3.  
  4. $container->setAlias(Profiler::class, 'profiler');

Updating the Web Debug Toolbar After AJAX Requests

Single-page applications (SPA) are web applications that interact with theuser by dynamically rewriting the current page rather than loading entire newpages from a server.

By default, the debug toolbar displays the information of the initial page loadand doesn't refresh after each AJAX request. However, you can set theSymfony-Debug-Toolbar-Replace header to a value of 1 in the response tothe AJAX request to force the refresh of the toolbar:

  1. $response->headers->set('Symfony-Debug-Toolbar-Replace', 1);

Ideally this header should only be set during development and not forproduction. To do that, create an event subscriberand listen to the kernel.responseevent:

  1. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  2.  
  3. // ...
  4.  
  5. public function onKernelResponse(ResponseEvent $event)
  6. {
  7. if (!$this->getKernel()->isDebug()) {
  8. return;
  9. }
  10.  
  11. $response = $event->getResponse();
  12. $response->headers->set('Symfony-Debug-Toolbar-Replace', 1);
  13. }