Skip to content

Commit

Permalink
[FrameworkBundle][HttpKernel] Add the ability to enable the profiler …
Browse files Browse the repository at this point in the history
…using a parameter
  • Loading branch information
dunglas authored and fabpot committed Oct 30, 2021
1 parent b2fc70b commit eecff07
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@ CHANGELOG
* Add `set_content_language_from_locale` config option to automatically set the `Content-Language` HTTP response header based on the Request locale
* Deprecate the `framework.translator.enabled_locales`, use `framework.enabled_locales` instead
* Add autowiring alias for `HttpCache\StoreInterface`
* Add the ability to enable the profiler using a request query parameter, body parameter or attribute
* Deprecate the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead
* Deprecate the public `profiler` service to private
* Deprecate `get()`, `has()`, `getDoctrine()`, and `dispatchMessage()` in `AbstractController`, use method/constructor injection instead
Expand Down
Expand Up @@ -315,6 +315,7 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode)
->canBeEnabled()
->children()
->booleanNode('collect')->defaultTrue()->end()
->scalarNode('collect_parameter')->defaultNull()->info('The name of the parameter to use to enable or disable collection on a per request basis')->end()
->booleanNode('only_exceptions')->defaultFalse()->end()
->booleanNode('only_main_requests')->defaultFalse()->end()
->booleanNode('only_master_requests')->setDeprecated('symfony/framework-bundle', '5.3', 'Option "%node%" at "%path%" is deprecated, use "only_main_requests" instead.')->defaultFalse()->end()
Expand Down
Expand Up @@ -770,6 +770,9 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
$container->getDefinition('profiler')
->addArgument($config['collect'])
->addTag('kernel.reset', ['method' => 'reset']);

$container->getDefinition('profiler_listener')
->addArgument($config['collect_parameter']);
}

private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
Expand Down
Expand Up @@ -91,6 +91,7 @@

<xsd:complexType name="profiler">
<xsd:attribute name="collect" type="xsd:string" />
<xsd:attribute name="collect-parameter" type="xsd:string" />
<xsd:attribute name="only-exceptions" type="xsd:string" />
<xsd:attribute name="only-main-requests" type="xsd:string" />
<xsd:attribute name="only-master-requests" type="xsd:string" />
Expand Down
Expand Up @@ -405,6 +405,7 @@ protected static function getBundleDefaultConfig()
'only_main_requests' => false,
'dsn' => 'file:%kernel.cache_dir%/profiler',
'collect' => true,
'collect_parameter' => null,
],
'translator' => [
'enabled' => !class_exists(FullStack::class),
Expand Down
Expand Up @@ -36,6 +36,27 @@ public function testProfilerIsDisabled($insulate)
$this->assertNull($client->getProfile());
}

/**
* @dataProvider getConfigs
*/
public function testProfilerCollectParameter($insulate)
{
$client = $this->createClient(['test_case' => 'ProfilerCollectParameter', 'root_config' => 'config.yml']);
if ($insulate) {
$client->insulate();
}

$client->request('GET', '/profiler');
$this->assertNull($client->getProfile());

// enable the profiler for the next request
$client->request('GET', '/profiler?profile=1');
$this->assertIsObject($client->getProfile());

$client->request('GET', '/profiler');
$this->assertNull($client->getProfile());
}

public function getConfigs()
{
return [
Expand Down
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;

return [
new FrameworkBundle(),
new TestBundle(),
];
@@ -0,0 +1,8 @@
imports:
- { resource: ../config/default.yml }

framework:
profiler:
enabled: true
collect: false
collect_parameter: profile
@@ -0,0 +1,2 @@
_sessiontest_bundle:
resource: '@TestBundle/Resources/config/routing.yml'
1 change: 1 addition & 0 deletions src/Symfony/Component/HttpKernel/CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
5.4
---

* Add the ability to enable the profiler using a request query parameter, body parameter or attribute
* Deprecate `AbstractTestSessionListener::getSession` inject a session in the request instead
* Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener`
* Add support for configuring log level, and status code by exception class
Expand Down
Expand Up @@ -36,13 +36,14 @@ class ProfilerListener implements EventSubscriberInterface
protected $exception;
protected $profiles;
protected $requestStack;
protected $collectParameter;
protected $parents;

/**
* @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise
* @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise
*/
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false)
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null)
{
$this->profiler = $profiler;
$this->matcher = $matcher;
Expand All @@ -51,6 +52,7 @@ public function __construct(Profiler $profiler, RequestStack $requestStack, Requ
$this->profiles = new \SplObjectStorage();
$this->parents = new \SplObjectStorage();
$this->requestStack = $requestStack;
$this->collectParameter = $collectParameter;
}

/**
Expand Down Expand Up @@ -79,6 +81,10 @@ public function onKernelResponse(ResponseEvent $event)
}

$request = $event->getRequest();
if (null !== $this->collectParameter && null !== $collectParameterValue = $request->get($this->collectParameter)) {
true === $collectParameterValue || filter_var($collectParameterValue, \FILTER_VALIDATE_BOOLEAN) ? $this->profiler->enable() : $this->profiler->disable();
}

$exception = $this->exception;
$this->exception = null;

Expand Down
Expand Up @@ -59,4 +59,42 @@ public function testKernelTerminate()

$listener->onKernelTerminate(new TerminateEvent($kernel, $mainRequest, $response));
}

/**
* @dataProvider collectRequestProvider
*/
public function testCollectParameter(Request $request, ?bool $enable)
{
$profile = new Profile('token');

$profiler = $this->createMock(Profiler::class);
$profiler->expects($this->once())
->method('collect')
->willReturn($profile);

$profiler
->expects(null === $enable ? $this->never() : $this->once())
->method($enable ? 'enable' : 'disable');

$kernel = $this->createMock(HttpKernelInterface::class);
$response = new Response();

$requestStack = new RequestStack();
$requestStack->push($request);

$listener = new ProfilerListener($profiler, $requestStack, null, false, false, 'profile');

$listener->onKernelResponse(new ResponseEvent($kernel, $request, Kernel::MAIN_REQUEST, $response));
}

public function collectRequestProvider(): iterable
{
yield [Request::create('/'), null];
yield [Request::create('/', 'GET', ['profile' => '1']), true];
yield [Request::create('/', 'GET', ['profile' => '0']), false];

$request = Request::create('/');
$request->attributes->set('profile', true);
yield [$request, true];
}
}

0 comments on commit eecff07

Please sign in to comment.