Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract the profiler to a new component #14809

Closed
wants to merge 2 commits into from
Closed

Conversation

jelte
Copy link

@jelte jelte commented May 31, 2015

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? yes
Tests pass? yes
Fixed tickets #11263
License MIT
Doc PR symfony/symfony-docs#5422

This pull request is a replacement for #10374

This pull request extracts the HTTP profiler from the HttpKernel component to a new dedicated component: Profiler.

The goals are to improve the general architecture and usability of the component as stated by @webmozart ( #10374 (comment) )
as it stands now no BC is broken as the original DataCollectors are still supported by the new Profiler.

New DataCollectors and Profiler no longer require a Request.
DataCollectors are should be able to collect data from other sources, which will prevent some ugly hacks that were previously required, they will still require to listen to events to collect the data, I don't see a way around this, but this doesn't seem a big issue.

If a DataCollector requires the Request, it should have the RequestStack and get it from there, the Responses can be added just like Controllers are added, by subscribing to the Kernel Events.

Changes

  • Profiler is no longer capable of searching or retrieving profiles, developers should use the ProfilerStorage directly for these functionalities.
  • DataCollectors are no longer added to the Profile. A ProfileDataInterface object is added instead.
  • DataCollectors no longer have a name.
  • Saving the profile is independent if its indexes, this allows for storing other types of Profiles while using the same Profiler and ProfilerStorage. ( for example Console Commands )
  • Many of the DataCollectors have been moved to their respective Component under their Profiler namespace.

Profiling

$profiler = new Profiler($storageInterface);
$profiler->addCollector(new RequestDataCollector($requestStack));
$profiler->addCollector(new ExceptionDataCollector());
$profiler->addCollector(new FormDataCollector());

// Runtime data is collected
$profile = $profiler->profile();

$requestData = $profile->get('request');

// Late data is collected
$profiler->save($profile, array('url' => 'http://localhost/', 'ip' => '127.0.0.1', 'method' => 'GET', 'status_code' => 200, 'profile_type' => 'http');

BC Breaks

DataCollectors

DataCollectors require getCollectedData.

solution:
commented the method in the DataCollectorInterface and added a fallback when the method does not exists.
This will the use the GenericProfileData to encapsulate the DataCollector, which will trigger a deprecated notice.

ProfilerStorages

ProfilerStorages require findBy which replaces the find method.

solution:
commented the method in the ProfilerStorageInterface.

Todo's

  • add additional tests to increase coverage.
  • add README.md
  • Test with Symfony demo
  • Convert Bundle & Bridge DataCollectors (if that does not break BC)
  • ConsoleProfiler
  • Move DataCollector to their related Component or Bridge
  • DoctrineDataCollector: Move collected data from DoctrineBundle to DoctrineBridge
  • Refactor FormDataCollector
  • Refactor DumpDataCollector as it has to many responsibilities
  • add tests for MysqlProfileStorage
  • Make ProfileData Serializable
  • Rename DataCollectorInterface::collect to getCollectedData
  • Remove getName from DataCollectorInterface
  • Remove storage methods (load, find, purge) from Profiler
  • Remove Collectors from Profile
  • Remove export & import from Profiler
  • move all deprecated code to the (deprecated) subclass.
  • Check for BC breaks ( and fix where possible )
  • add phpdocs where missing
  • squash pull request
  • submit changes to the documentation

Special thanks to @stof & @dosten for helping me out on the initial pull request ( #14763 )

@@ -33,13 +36,4 @@
* @api
*/
public function collect(Request $request, Response $response, \Exception $exception = null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you do not move this method definition to the new DataCollectorInterface and only keep this interface empty and extending the new one?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 reason for this, for one the new DataCollectorInterface doesn't have a collect function any more.
RuntimeDataCollectorInterface replace the old DataCollectorInterface, as I noticed some if not most use the LateDataCollectorInterface and have no use for a collect method.
For that reason I have removed the collect method from DataCollectorInterface.

The other reason is that the new profiler does not require a Request and Response, but to maintain BC I had to leave this in.

@jelte jelte force-pushed the profiler branch 2 times, most recently from 53b5f18 to 687afd2 Compare June 8, 2015 13:44
@@ -20,6 +20,7 @@
"symfony/event-dispatcher": "~2.5.9|~2.6,>=2.6.2|~3.0.0",
"symfony/http-foundation": "~2.5,>=2.5.4|~3.0.0",
"symfony/debug": "~2.6,>=2.6.2",
"symfony/profiler": "~2.7|~3.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is probably
"symfony/profiler": "~2.8|~3.0.0"

@mickaelandrieu
Copy link
Contributor

@jelte don't give up please, I need this component too and I will be happy to help you 👍

@jelte
Copy link
Author

jelte commented Jun 8, 2015

@mickaelandrieu I won't, a lot of the comments are issues coming from the original files, any others are good learning for me.

@phansys
Copy link
Contributor

phansys commented Jun 8, 2015

I think you should use PHP-CS-FIXER to solve majority of your CS issues. It should leave a clear code to make the review easy.

@jelte
Copy link
Author

jelte commented Jun 8, 2015

For some of the DataCollectors I have the feeling they do not belong in the Profiler:

  • DumpDataCollector => VarDumper or DebugBundle, the DumpListener from HttpKernel should probably be moved as well.
  • EventDataCollector => EventDispatcher
  • LoggerDataCollector => MonologBridge, the DebugLoggerInterface should also be moved ( should be done carefully as this is used in the ExceptionListener )
  • RequestDataCollector => HttpKernel
  • RouteDataCollector => Routing

This is already done for the FormDataCollector and SecurityDataCollector.

Collectors that would remain in the Profiler are:

  • ConfigDataCollector. I am considering splitting this one to ProjectDataCollector, SymfonyDataCollector and ConfigDataCollector, but this will have some impact on the WebProfilerBundle.
  • MemoryDataCollector
  • TimeDataCollector

@mickaelandrieu
Copy link
Contributor

@jelte totaly agree but I disagree to make new strong dependencies between the components.

Maybe FrameworkBundle is the better place for theses collectors ?

@jelte
Copy link
Author

jelte commented Jun 8, 2015

@mickaelandrieu I would keep them in their respective Bundle or Bridge if one exists, rather than dumping everything in the FrameworkBundle.

  • DumpDataCollector => DebugBundle
  • EventDataCollector => FrameworkBundle
  • LoggerDataCollector => MonologBridge
  • RequestDataCollector => FrameworkBundle
  • RouteDataCollector => FrameworkBundle

@mickaelandrieu
Copy link
Contributor

@jelte agree :) /c @fabpot what do you think ?

@stof
Copy link
Member

stof commented Jun 9, 2015

Please don't move them into bundles. It would make the profiler unusable for people using the components (Silex for instance).

@mickaelandrieu
Copy link
Contributor

@stof humm, how about a symfony-collectors package then ?

@jelte
Copy link
Author

jelte commented Jun 9, 2015

@stof I understand, that's why I suggested to keep them in the component they belong to (like what is done with the FormProfiler at the moment).
@mickaelandrieu this will just move the issue from profiler to symfony-collectors (creating a bundle that has dependency to everything).

{
$this->registry = $registry;
$this->connections = $registry->getConnectionNames();
$this->managers = $registry->getManagerNames();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could remove managers and connections properties, we don't need them here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the Doctrine bridge, the new collector might be a good time to move the extra data collected in DoctrineBundle to the bridge itself btw.

@stof
Copy link
Member

stof commented Jun 9, 2015

Well, once we have a dedicated component for the profiler, component profilers could indeed go in each component. this would be consistent with the fact that ContainerAwareDispatcher is in the EventDispatcher rather than the DI component for instance.
Each component with a profiling collector would then have an optional dependency on the Profiler component (optional because using the collector would be optional of course, and useful only for people using the profiler component)

@jelte
Copy link
Author

jelte commented Nov 12, 2015

At the moment, I have resolved all deprecation notices.
(Build still fails, but they are the same failures as the 2.8 branch)

@jelte
Copy link
Author

jelte commented Nov 14, 2015

@stof @fabpot

ping @symfony/deciders can someone take a look at this contribution? At least to say if this may have a chance to be merged or not?

@Tobion
Copy link
Member

Tobion commented Nov 14, 2015

@jelte it most likely will not be part of 2.8/3.0 as we are trying to stabilize now and not make big changes. But considering the amount of work done here, I assume it's worth to merge this in 3.1 later.

@ghost
Copy link

ghost commented Nov 15, 2015

As I currently understand I need to enable debug on the AppKernel to use the time measure in the Profiler, right?

My idea was to enable the profiler in our "testing" environment in combination with enabled caching to check the performance of our application. The issue is that if I enable 'debug' in the AppKernel I will trigger a lot of other things which will result in non-caching (for example the CSS files are generated and not cached).

Will this new Profiler component fix this issue and will it provide a good solution for this?

@jelte
Copy link
Author

jelte commented Nov 16, 2015

@Tobion Figured as much, just wanted confirmation, will keep this up-to-date as frequently as possible.

@jelte
Copy link
Author

jelte commented Nov 16, 2015

@JHGitty You can already do this now by defining a second Profiler and ProfilerListener and only adding the TimeCollector to it.
Just put it in a separate xml which is only loaded on your "testing" environment.

     <service id="test.profiler_listener" class="Symfony\Component\HttpKernel\EventListener\ProfilerListener">
            <tag name="kernel.event_subscriber" />
            <argument type="service" id="test.profiler" />
            <argument type="service" id="test.request_matcher"/>
            <argument>false</argument>
            <argument>false</argument>
            <argument type="service" id="request_stack" />
        </service>

        <service id="test.profiler" class="Symfony\Component\HttpKernel\Profiler\Profiler">
            <argument type="service" id="test.profiler.storage" />
            <call method="add">
                <argument type="service" id="data_collector.time"/>
            </call>
        </service>

Idea would be just to config what you'd need and nothing more. This would only get you the data being generated.

@ghost
Copy link

ghost commented Nov 16, 2015

@jelte Is there any documentation about this? I think somebody should add a documentation page about this. I don't think that I am the only person who like to check performance with enabled cache.

@stof
Copy link
Member

stof commented Nov 16, 2015

@jelte you should probably use a separate time collector to avoid issues (collectors are stateful)

@JHGitty note that registering the time panel alone will not help much: most places registering data into the stopwatch component are controlled by the debug mode in FrameworkBundle: wrapping the event dispatcher into a traceable one to log timing info comes at a cost, which is why it is only done in debug mode (where we add more debugging info at the expense of performance).
The symfony profiler is a debugging profiler (to know what happens in your request), but not a timing performance profiler (for which the profiling overhead must be as small as possible). You should use a real performance profiler for that (for instance, https://blackfire.io which is free for the basic features).

Anyway, this should be discussed elsewhere than in this PR as it is unrelated (and the PR discussion should stay focused on reviewing the PR)

@pyrech
Copy link
Contributor

pyrech commented Jan 24, 2016

Now that 3.0 was released and 3.1 development is in progress, is this PR still considered by the core team? @jelte already did an awesome job but the PR now obviously needs to be rebased.

@mickaelandrieu
Copy link
Contributor

@pyrech we can't ask to @jelte to maintain a fork for years too.

Before ask for rebase, maybe someone from the core team could say if this contribution could be accepted or not?

Other way to do: fork once and for all, and make a bundle.

@Taluu
Copy link
Contributor

Taluu commented Mar 9, 2016

A bundle is not a solution... but making a real lib is (as all components can be used independently)

@mickaelandrieu
Copy link
Contributor

@Taluu sure I saw this bundle as an implementation of this fork (which is already a library/component)

@jelte
Copy link
Author

jelte commented Mar 14, 2016

Just to give everyone a little update,
I just started to rebase this on the current 3.0, I will update as soon as possible.

@Shine-neko
Copy link

@jelte ?

@nicolas-grekas nicolas-grekas added this to the 3.x milestone Dec 6, 2016
@Koc
Copy link
Contributor

Koc commented May 1, 2017

Fixes #21141

@@ -22,6 +22,8 @@
* DoctrineDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 2.8, to be removed in 3.0. Use Symfony\Bridge\Doctrine\Profiler\DoctrineDataCollector instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 4.0 ?

@@ -20,6 +20,8 @@
* TwigDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 2.8, to be removed in 3.0. Use Symfony\Bridge\Twig\Profiler\TwigDataCollector instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4.0 ?

@Shine-neko
Copy link

@fabpot planned for 4.0 ?

@fabpot
Copy link
Member

fabpot commented Jul 6, 2017

I'm closing this one. I'm not convinced that we should have a decoupled profiler. The profiler does the job as is and the fact it's tied to Request/Response is part of the design that I don't want to change. I know that it took time for me to make that decision, but after all this time, I still think that's not something that needs to be done. Thanks for working on this.

@fabpot fabpot closed this Jul 6, 2017
@Wirone
Copy link
Contributor

Wirone commented Sep 27, 2018

This would be soooooooo helpful and I am so disappointed by @fabpot's decision :( Some applications doesn't even have HTTP context, they're 100% CLI and profiling them is a must have. I don't understand why it was rejected, at this point it would be probably crucial..

Feel bad for you, @jelte :(

nicolas-grekas added a commit that referenced this pull request Oct 17, 2023
…le] Enable profiling commands (HeahDude)

This PR was merged into the 6.4 branch.

Discussion
----------

[Console][FrameworkBundle][HttpKernel][WebProfilerBundle] Enable profiling commands

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Fix #45241
| License       | MIT
| Doc PR        | ~

TLDR;

I've shown a POC of this feature at the Symfony Live Paris last April to some of the core team members (ping `@nicolas`-grekas, `@stof`, `@lyrixx`, `@chalasr`, `@GromNaN`).
I propose here a new work from scratch addressing the comments I already got and based on Javier's profiler redesign (#47148).
Reviews should better be done by commits.

Summary
---------
This PR aims to leverage the profiler and its collectors by using a `VirtualRequestStack` to aggregate data on virtual requests.
Such requests are obfuscated by default to avoid side effects.
It can feel like a hack... or a pragmatic way to get, without much complexity, tons of useful feedback on what's going on during console execution, from basic info about the command, time/memory metrics, to every existing features already available in HTTP context: events, message dispatching, http requests, emails, serialization, validation, cache, database queries... and so on, all that just out of the box!

Previous work
--------------

There were some work to extract the Profiler logic in a dedicated component, that proved to require a lot of complexity and BC breaks in the API:
* #10374
* #14809 (see #14809 (comment))
* #20502

Screenshots
------------
For now I've focused only on the functional parts.

<details><summary>Search view</summary>
<img width="1221" alt="Screenshot 2022-08-28 at 11 29 25 PM" src="https://user-images.githubusercontent.com/10107633/187095381-851f6be5-cf8c-4fec-aa7b-9f9f80bf8404.png">
</details>
<details><summary>Command panel</summary>
<img width="1210" alt="Screenshot 2022-08-28 at 11 30 54 PM" src="https://user-images.githubusercontent.com/10107633/187095971-de8f9b85-eeb4-48cf-aff7-fdac0c6f9264.png">
<img width="974" alt="Screenshot 2022-08-28 at 11 31 08 PM" src="https://user-images.githubusercontent.com/10107633/187095980-337f4373-ebe5-4de5-bfb4-3715be868274.png">
<img width="962" alt="Screenshot 2022-08-28 at 11 31 21 PM" src="https://user-images.githubusercontent.com/10107633/187096022-ab18f70a-704a-4c75-81a6-43ca5b66eb9a.png">
<img width="964" alt="Screenshot 2022-08-28 at 11 31 34 PM" src="https://user-images.githubusercontent.com/10107633/187096037-cc45805e-ba65-447f-bca6-2d2ea38239b8.png">

If the command is signal-able the following panel will be available:
<img width="961" alt="Screenshot 2022-08-28 at 11 31 46 PM" src="https://user-images.githubusercontent.com/10107633/187096084-2f6a39be-a780-411b-9000-b9ae3407e82b.png">

If sub commands are run using `$this->getApplication()->run()` sub profiles will be shown as for requests:
<img width="696" alt="Screenshot 2022-08-28 at 11 31 56 PM" src="https://user-images.githubusercontent.com/10107633/187096105-bb7e4a84-42bc-47ed-9f58-527a771c48cc.png">
</details>

The server tab is the same as in the request panel.

<details><summary>Performance panel</summary>
<img width="977" alt="Screenshot 2022-08-28 at 11 32 23 PM" src="https://user-images.githubusercontent.com/10107633/187096138-3ff3f347-61c7-4ade-8c73-b48d5b504c04.png">
<img width="969" alt="Screenshot 2022-08-28 at 11 32 32 PM" src="https://user-images.githubusercontent.com/10107633/187096168-35be4773-4941-4e5e-8dd4-f6cc009e5d48.png">
</details>
<details>
<summary>Failing command</summary>
The exception panel is shown by default as for requests:
<img width="1217" alt="Screenshot 2022-08-28 at 11 33 42 PM" src="https://user-images.githubusercontent.com/10107633/187096210-7b206c72-c2e4-4eb3-9978-916cd3dd6cd6.png">
</details>

<details>
<summary>Sub command</summary>
<img width="1217" alt="Screenshot 2022-08-28 at 11 33 19 PM" src="https://user-images.githubusercontent.com/10107633/187096188-a090fb91-b7b8-4f98-a1d7-99b3605bf48b.png">
</details>

<details>
<summary>Profile token when verbose</summary>
(clickable links with compatible terminals)
<img width="534" alt="Screenshot 2022-08-28 at 11 26 51 PM" src="https://user-images.githubusercontent.com/10107633/187096349-8f7619b2-feb4-427c-a315-f4a844536316.png">
</details>

<details>
<summary>Command interrupted by signal</summary>
<img width="1246" alt="Screenshot 2022-10-22 at 4 16 37 PM" src="https://user-images.githubusercontent.com/10107633/197344164-50d72a25-a6e7-4e77-ad87-2d5f54b29b93.png">
</details>

Opt-in profiling
---------------

Use the new global option `--profile` (in debug only) to profile a command.

Future scopes
--------------

* When I've discussed the limitation of profiling long running processes such as `messenger:consume` with `@GromNaN` (one of the reasons why I've added an `excludes` option), he told that it would be nice it we could find a way to profile consumers as well.
So I've added ~an abstract `VirtualRequest`~ a `_virtual_type` request attribute and a `virtualType` property to profiles, that will allow to create a `MessengerWorkerRequest` and  a new type of profile with ease in a follow-up PR if the current implementation is accepted.
* We could add some dedicated casters for input and output in the `VarDumper` component (/cc `@nicolas`-grekas)
* It could be interesting to decorate and collect traces from some helpers (i.e. when running processes)
* ~Add a global option in debug to enable/disable the profiler on the fly when running commands (e.g. a negatable `--profile` flag)~
  **[update] implemented in current scope in replacement of semantic config.**
* Extract profiling to a new component.

Limitations
-----------
* ~No sub profiles are created when using `$this->getApplication()->find(...)->run()` because events (needed by the profiler to hook into) are dispatched from `Application::run()`, not from `Command::run()`.~
  **[update] The docs has been updated in symfony/symfony-docs#18741
* ~No profiles are created when killing the command process (i.e. using `ctrl-C`, should we add a handler to some signals to force saving profiles?~
  **[update] I've added support for this.**
* ~Signals as int may not be as useful as they could in the profiler pages, does it worth trying to add a label to some (knowing that some signals can have different constants (labels) with the same int value)?~
  **[update] done thanks to #50663
* ~Long running processes should be excluded via configuration to avoid memory leaks~
  **[update] profiling is now opt-in using the `--profile` option.**
* Profiling `messenger:consume` does not work since the kernel is reset after handling a message.

__________________

TODO
------

* [x] I've left some todos inside the code for reviewers to share they thought before I try going further
* [x] Add a few tests
* [ ] Get help for the UI (new top nav, ~svg for the command panel~) /cc `@javiereguiluz`
* ~PR on `symfony/recipes` to add the new `framework.profiler.cli` node~

Commits
-------

82914ba [Console][FrameworkBundle][HttpKernel][WebProfilerBundle] Enable profiling commands
symfony-splitter pushed a commit to symfony/framework-bundle that referenced this pull request Oct 17, 2023
…le] Enable profiling commands (HeahDude)

This PR was merged into the 6.4 branch.

Discussion
----------

[Console][FrameworkBundle][HttpKernel][WebProfilerBundle] Enable profiling commands

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Fix #45241
| License       | MIT
| Doc PR        | ~

TLDR;

I've shown a POC of this feature at the Symfony Live Paris last April to some of the core team members (ping `@nicolas`-grekas, `@stof`, `@lyrixx`, `@chalasr`, `@GromNaN`).
I propose here a new work from scratch addressing the comments I already got and based on Javier's profiler redesign (#47148).
Reviews should better be done by commits.

Summary
---------
This PR aims to leverage the profiler and its collectors by using a `VirtualRequestStack` to aggregate data on virtual requests.
Such requests are obfuscated by default to avoid side effects.
It can feel like a hack... or a pragmatic way to get, without much complexity, tons of useful feedback on what's going on during console execution, from basic info about the command, time/memory metrics, to every existing features already available in HTTP context: events, message dispatching, http requests, emails, serialization, validation, cache, database queries... and so on, all that just out of the box!

Previous work
--------------

There were some work to extract the Profiler logic in a dedicated component, that proved to require a lot of complexity and BC breaks in the API:
* #10374
* #14809 (see symfony/symfony#14809 (comment))
* #20502

Screenshots
------------
For now I've focused only on the functional parts.

<details><summary>Search view</summary>
<img width="1221" alt="Screenshot 2022-08-28 at 11 29 25 PM" src="https://user-images.githubusercontent.com/10107633/187095381-851f6be5-cf8c-4fec-aa7b-9f9f80bf8404.png">
</details>
<details><summary>Command panel</summary>
<img width="1210" alt="Screenshot 2022-08-28 at 11 30 54 PM" src="https://user-images.githubusercontent.com/10107633/187095971-de8f9b85-eeb4-48cf-aff7-fdac0c6f9264.png">
<img width="974" alt="Screenshot 2022-08-28 at 11 31 08 PM" src="https://user-images.githubusercontent.com/10107633/187095980-337f4373-ebe5-4de5-bfb4-3715be868274.png">
<img width="962" alt="Screenshot 2022-08-28 at 11 31 21 PM" src="https://user-images.githubusercontent.com/10107633/187096022-ab18f70a-704a-4c75-81a6-43ca5b66eb9a.png">
<img width="964" alt="Screenshot 2022-08-28 at 11 31 34 PM" src="https://user-images.githubusercontent.com/10107633/187096037-cc45805e-ba65-447f-bca6-2d2ea38239b8.png">

If the command is signal-able the following panel will be available:
<img width="961" alt="Screenshot 2022-08-28 at 11 31 46 PM" src="https://user-images.githubusercontent.com/10107633/187096084-2f6a39be-a780-411b-9000-b9ae3407e82b.png">

If sub commands are run using `$this->getApplication()->run()` sub profiles will be shown as for requests:
<img width="696" alt="Screenshot 2022-08-28 at 11 31 56 PM" src="https://user-images.githubusercontent.com/10107633/187096105-bb7e4a84-42bc-47ed-9f58-527a771c48cc.png">
</details>

The server tab is the same as in the request panel.

<details><summary>Performance panel</summary>
<img width="977" alt="Screenshot 2022-08-28 at 11 32 23 PM" src="https://user-images.githubusercontent.com/10107633/187096138-3ff3f347-61c7-4ade-8c73-b48d5b504c04.png">
<img width="969" alt="Screenshot 2022-08-28 at 11 32 32 PM" src="https://user-images.githubusercontent.com/10107633/187096168-35be4773-4941-4e5e-8dd4-f6cc009e5d48.png">
</details>
<details>
<summary>Failing command</summary>
The exception panel is shown by default as for requests:
<img width="1217" alt="Screenshot 2022-08-28 at 11 33 42 PM" src="https://user-images.githubusercontent.com/10107633/187096210-7b206c72-c2e4-4eb3-9978-916cd3dd6cd6.png">
</details>

<details>
<summary>Sub command</summary>
<img width="1217" alt="Screenshot 2022-08-28 at 11 33 19 PM" src="https://user-images.githubusercontent.com/10107633/187096188-a090fb91-b7b8-4f98-a1d7-99b3605bf48b.png">
</details>

<details>
<summary>Profile token when verbose</summary>
(clickable links with compatible terminals)
<img width="534" alt="Screenshot 2022-08-28 at 11 26 51 PM" src="https://user-images.githubusercontent.com/10107633/187096349-8f7619b2-feb4-427c-a315-f4a844536316.png">
</details>

<details>
<summary>Command interrupted by signal</summary>
<img width="1246" alt="Screenshot 2022-10-22 at 4 16 37 PM" src="https://user-images.githubusercontent.com/10107633/197344164-50d72a25-a6e7-4e77-ad87-2d5f54b29b93.png">
</details>

Opt-in profiling
---------------

Use the new global option `--profile` (in debug only) to profile a command.

Future scopes
--------------

* When I've discussed the limitation of profiling long running processes such as `messenger:consume` with `@GromNaN` (one of the reasons why I've added an `excludes` option), he told that it would be nice it we could find a way to profile consumers as well.
So I've added ~an abstract `VirtualRequest`~ a `_virtual_type` request attribute and a `virtualType` property to profiles, that will allow to create a `MessengerWorkerRequest` and  a new type of profile with ease in a follow-up PR if the current implementation is accepted.
* We could add some dedicated casters for input and output in the `VarDumper` component (/cc `@nicolas`-grekas)
* It could be interesting to decorate and collect traces from some helpers (i.e. when running processes)
* ~Add a global option in debug to enable/disable the profiler on the fly when running commands (e.g. a negatable `--profile` flag)~
  **[update] implemented in current scope in replacement of semantic config.**
* Extract profiling to a new component.

Limitations
-----------
* ~No sub profiles are created when using `$this->getApplication()->find(...)->run()` because events (needed by the profiler to hook into) are dispatched from `Application::run()`, not from `Command::run()`.~
  **[update] The docs has been updated in symfony/symfony-docs#18741
* ~No profiles are created when killing the command process (i.e. using `ctrl-C`, should we add a handler to some signals to force saving profiles?~
  **[update] I've added support for this.**
* ~Signals as int may not be as useful as they could in the profiler pages, does it worth trying to add a label to some (knowing that some signals can have different constants (labels) with the same int value)?~
  **[update] done thanks to symfony/symfony#50663
* ~Long running processes should be excluded via configuration to avoid memory leaks~
  **[update] profiling is now opt-in using the `--profile` option.**
* Profiling `messenger:consume` does not work since the kernel is reset after handling a message.

__________________

TODO
------

* [x] I've left some todos inside the code for reviewers to share they thought before I try going further
* [x] Add a few tests
* [ ] Get help for the UI (new top nav, ~svg for the command panel~) /cc `@javiereguiluz`
* ~PR on `symfony/recipes` to add the new `framework.profiler.cli` node~

Commits
-------

82914bab0d [Console][FrameworkBundle][HttpKernel][WebProfilerBundle] Enable profiling commands
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet