diff --git a/_build/redirection_map b/_build/redirection_map index 5bc5ef3a0df..5fbe425b16e 100644 --- a/_build/redirection_map +++ b/_build/redirection_map @@ -405,3 +405,6 @@ /console/logging /console /reference/forms/twig_reference /form/form_customization /form/rendering /form/form_customization +/profiler/matchers /profiler +/profiler/profiling_data /profiler +/profiler/wdt_follow_ajax /profiler diff --git a/_images/profiler/web-interface.png b/_images/profiler/web-interface.png new file mode 100644 index 00000000000..2e6c6061892 Binary files /dev/null and b/_images/profiler/web-interface.png differ diff --git a/components/stopwatch.rst b/components/stopwatch.rst index c792b0eb90f..1619070efb7 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -63,9 +63,8 @@ Symfony Profiler tool uses categories to nicely color-code different events. .. tip:: - When you want to show events in the Symfony profiler, autowire - ``Symfony\Component\Stopwatch\Stopwatch`` into your service. Each category - is shown on a separate line. + Read :ref:`this article ` to learn more about + integrating the Stopwatch component into the Symfony profiler. Periods ------- diff --git a/profiler.rst b/profiler.rst index 6deabbe4703..6fe1840bab9 100644 --- a/profiler.rst +++ b/profiler.rst @@ -2,10 +2,8 @@ Profiler ======== The profiler is a powerful **development tool** that gives detailed information -about the execution of any request. - -**Never** enable the profiler in production environments as it will lead to -major security vulnerabilities in your project. +about the execution of any request. **Never** enable the profiler in production +environments as it will lead to major security vulnerabilities in your project. Installation ------------ @@ -17,10 +15,207 @@ install the profiler before using it: $ composer require --dev symfony/profiler-pack +Now browse any page of your application in the development environment to let +the profiler collect information. Then, click on any element of the debug +toolbar injected at the bottom of your pages to open the web interface of the +Symfony Profiler, which will look like this: + +.. image:: /_images/profiler/web-interface.png + :align: center + :class: with-browser + +Accessing Profiling Data Programmatically +----------------------------------------- + +Most of the times, the profiler information is accessed and analyzed using its +web-based interface. However, you can also retrieve profiling information +programmatically thanks to the methods provided by the ``profiler`` service. + +When the response object is available, use the +:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::loadProfileFromResponse` +method to access to its associated profile:: + + // ... $profiler is the 'profiler' service + $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 the +:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::loadProfile` method:: + + $token = $response->headers->get('X-Debug-Token'); + $profile = $profiler->loadProfile($token); + +.. tip:: + + When the profiler is enabled but not the web debug toolbar, inspect the page + with your browser's developer tools to get the value of the ``X-Debug-Token`` + HTTP header. + +The ``profiler`` service also provides the +:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::find` method to +look for tokens based on some criteria:: + + // gets the latest 10 tokens + $tokens = $profiler->find('', '', 10, '', '', ''); + + // gets the latest 10 tokens for all URL containing /admin/ + $tokens = $profiler->find('', '/admin/', 10, '', '', ''); + + // gets the latest 10 tokens for local POST requests + $tokens = $profiler->find('127.0.0.1', '', 10, 'POST', '', ''); + + // gets the latest 10 tokens for requests that happened between 2 and 4 days ago + $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: + +.. code-block:: terminal + + $ php bin/console debug:container --tag=data_collector + +You can also :doc:`create your own data collector ` to +store any data generated by your app and display it in the debug toolbar and the +profiler web interface. + +.. _profiler-timing-execution: + +Timing the Execution of the Application +--------------------------------------- + +If you want to measure the time some tasks take in your application, there's no +need to create a custom data collector. Instead, use the `Stopwatch component`_ +which provides utilities to profile code and displayes the results on the +"Performance" panel of the Profiler web interface. + +When using :ref:`autowiring `, type-hint any argument with +the :class:`Symfony\\Component\\Stopwatch\\Stopwatch` class and Symfony will +inject the Stopwatch service. Then, use the ``start()``, ``lapse()`` and +``stop()`` methods to measure time:: + + // a user signs up and the timer starts... + $stopwatch->start('user-sign-up'); + + // ...do things to sign up the user... + $stopwatch->lapse('user-sign-up'); + + // ...the sign up process is finished + $stopwatch->stop('user-sign-up'); + +.. tip:: + + Consider using a professional profiler such as `Blackfire`_ to measure and + analyze the execution of your application in detail. + +Enabling the Profiler Conditionally +----------------------------------- + +.. caution:: + + The possibility to use a matcher to enable the profiler conditionally was + removed in Symfony 4.0. + +Symfony Profiler cannot be enabled/disabled conditionally using matchers, because +that feature was removed in Symfony 4.0. However, you can use the ``enable()`` +and ``disable()`` methods of the :class:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler` +class in your controllers to manage the profiler programmatically:: + + use Symfony\Component\HttpKernel\Profiler\Profiler; + // ... + + class DefaultController + { + // ... + + public function someMethod(?Profiler $profiler) + { + // $profiler won't be set if your environment doesn't have the profiler (like prod, by default) + if (null !== $profiler) { + // if it exists, disable the profiler for this particular controller action + $profiler->disable(); + } + + // ... + } + } + +In order for the profiler to be injected into your controller you need to +create an alias pointing to the existing ``profiler`` service: + +.. configuration-block:: + + .. code-block:: yaml + + # config/services_dev.yaml + services: + Symfony\Component\HttpKernel\Profiler\Profiler: '@profiler' + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // config/services_dev.php + use Symfony\Component\HttpKernel\Profiler\Profiler; + + $container->setAlias(Profiler::class, 'profiler'); + +Updating the Web Debug Toolbar After AJAX Requests +-------------------------------------------------- + +`Single-page applications`_ (SPA) are web applications that interact with the +user by dynamically rewriting the current page rather than loading entire new +pages from a server. + +By default, the debug toolbar displays the information of the initial page load +and doesn't refresh after each AJAX request. However, you can set the +``Symfony-Debug-Toolbar-Replace`` header to a value of ``1`` in the response to +the AJAX request to force the refresh of the toolbar:: + + $response->headers->set('Symfony-Debug-Toolbar-Replace', 1); + +Ideally this header should only be set during development and not for +production. To do that, create an :doc:`event subscriber ` +and listen to the :ref:`kernel.response` +event:: + + use Symfony\Component\HttpKernel\Event\FilterResponseEvent; + + // ... + + public function onKernelResponse(FilterResponseEvent $event) + { + if (!$this->getKernel()->isDebug()) { + return; + } + + $response = $event->getResponse(); + $response->headers->set('Symfony-Debug-Toolbar-Replace', 1); + } + .. toctree:: - :maxdepth: 1 + :hidden: profiler/data_collector - profiler/profiling_data - profiler/matchers - profiler/wdt_follow_ajax + +.. _`Single-page applications`: https://en.wikipedia.org/wiki/Single-page_application +.. _`Stopwatch component`: https://symfony.com/components/Stopwatch +.. _`Blackfire`: https://blackfire.io/ diff --git a/profiler/matchers.rst b/profiler/matchers.rst deleted file mode 100644 index ed6ae8afdfd..00000000000 --- a/profiler/matchers.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. index:: - single: Profiling; Matchers - -How to Use Matchers to Enable the Profiler Conditionally -======================================================== - -.. caution:: - - The possibility to use a matcher to enable the profiler conditionally was - removed in Symfony 4.0. - -Symfony Profiler cannot be enabled/disabled conditionally using matchers, because -that feature was removed in Symfony 4.0. However, you can use the ``enable()`` -and ``disable()`` methods of the :class:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler` -class in your controllers to manage the profiler programmatically:: - - use Symfony\Component\HttpKernel\Profiler\Profiler; - // ... - - class DefaultController - { - // ... - - public function someMethod(?Profiler $profiler) - { - // $profiler won't be set if your environment doesn't have the profiler (like prod, by default) - if (null !== $profiler) { - // if it exists, disable the profiler for this particular controller action - $profiler->disable(); - } - - // ... - } - } - -In order for the profiler to be injected into your controller you need to -create an alias pointing to the existing ``profiler`` service: - -.. configuration-block:: - - .. code-block:: yaml - - # config/services_dev.yaml - services: - Symfony\Component\HttpKernel\Profiler\Profiler: '@profiler' - - .. code-block:: xml - - - - - - - - - - - .. code-block:: php - - // config/services_dev.php - use Symfony\Component\HttpKernel\Profiler\Profiler; - - $container->setAlias(Profiler::class, 'profiler'); diff --git a/profiler/profiling_data.rst b/profiler/profiling_data.rst deleted file mode 100644 index 9eab1d91e97..00000000000 --- a/profiler/profiling_data.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. index:: - single: Profiling; Profiling data - -How to Access Profiling Data Programmatically -============================================= - -Most of the times, the profiler information is accessed and analyzed using its -web-based visualizer. However, you can also retrieve profiling information -programmatically thanks to the methods provided by the ``profiler`` service. - -When the response object is available, use the -:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::loadProfileFromResponse` -method to access to its associated profile:: - - // ... $profiler is the 'profiler' service - $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 the -:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::loadProfile` method:: - - $token = $response->headers->get('X-Debug-Token'); - $profile = $profiler->loadProfile($token); - -.. tip:: - - When the profiler is enabled but not the web debug toolbar, inspect the page - with your browser's developer tools to get the value of the ``X-Debug-Token`` - HTTP header. - -The ``profiler`` service also provides the -:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::find` method to -look for tokens based on some criteria:: - - // gets the latest 10 tokens - $tokens = $profiler->find('', '', 10, '', '', ''); - - // gets the latest 10 tokens for all URL containing /admin/ - $tokens = $profiler->find('', '/admin/', 10, '', '', ''); - - // gets the latest 10 tokens for local POST requests - $tokens = $profiler->find('127.0.0.1', '', 10, 'POST', '', ''); - - // gets the latest 10 tokens for requests that happened between 2 and 4 days ago - $tokens = $profiler->find('', '', 10, '', '4 days ago', '2 days ago'); diff --git a/profiler/wdt_follow_ajax.rst b/profiler/wdt_follow_ajax.rst deleted file mode 100644 index 7918d281e54..00000000000 --- a/profiler/wdt_follow_ajax.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. index:: - single: Profiling: WDT Auto-update after AJAX Request - -How to Make the Web Debug Toolbar Auto-update After AJAX Requests -================================================================= - -For single page applications it would be more convenient if the toolbar -showed the information for the most recent AJAX request instead of the -initial page load. - -By setting the ``Symfony-Debug-Toolbar-Replace`` header to a value of ``1`` in the -AJAX request, the toolbar will be automatically reloaded for the request. The -header can be set on the response object:: - - $response->headers->set('Symfony-Debug-Toolbar-Replace', 1); - -Only Setting the Header During Development -------------------------------------------- - -Ideally this header should only be set during development and not for -production. This can be accomplished by setting the header in a -:ref:`kernel.response ` event listener:: - - use Symfony\Component\HttpKernel\Event\FilterResponseEvent; - - // ... - - public function onKernelResponse(FilterResponseEvent $event) - { - $response = $event->getResponse(); - - $response->headers->set('Symfony-Debug-Toolbar-Replace', 1); - } - -.. seealso:: - - Read more about :doc:`Symfony events `. - -If you are using Symfony Flex, you should define your event listener service in the -``config/services_dev.yml`` file so that it only exists in the ``dev`` environment. - -.. seealso:: - - Read more on - :doc:`creating dev only services `.