Skip to content

Commit f1d0dc0

Browse files
andreyboloninjaviereguiluz
authored andcommitted
[Profiler] Add conditional profiling example config
1 parent 9a5dbcc commit f1d0dc0

File tree

18 files changed

+321
-114
lines changed

18 files changed

+321
-114
lines changed

.doctor-rst.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ rules:
1818
ensure_order_of_code_blocks_in_configuration_block: ~
1919
extend_abstract_controller: ~
2020
# extension_xlf_instead_of_xliff: ~
21+
forbidden_directives:
22+
directives:
23+
- '.. index::'
2124
indention: ~
2225
lowercase_as_in_use_statements: ~
2326
max_blank_lines:

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
key: ${{ runner.os }}-doctor-rst-${{ steps.extract_base_branch.outputs.branch }}
7474

7575
- name: "Run DOCtor-RST"
76-
uses: docker://oskarstark/doctor-rst:1.41.3
76+
uses: docker://oskarstark/doctor-rst:1.42.1
7777
with:
7878
args: --short --error-format=github --cache-file=/github/workspace/.cache/doctor-rst.cache
7979

_build/composer.lock

Lines changed: 82 additions & 79 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/clock.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ for different use cases:
1717
:class:`Symfony\\Component\\Clock\\MockClock`
1818
Commonly used in tests as a replacement for the ``NativeClock`` to be able
1919
to freeze and change the current time using either ``sleep()`` or ``modify()``.
20-
:class:`Symfony\\Component\\Clock\\MonotonicClock``
20+
:class:`Symfony\\Component\\Clock\\MonotonicClock`
2121
Relies on ``hrtime()`` and provides a high resolution, monotonic clock,
2222
when you need a precise stopwatch.
2323

components/process.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ You can configure the options passed to the ``other_options`` argument of
109109
// this option allows a subprocess to continue running after the main script exited
110110
$process->setOptions(['create_new_console' => true]);
111111

112+
.. note::
113+
114+
The ``create_new_console`` option is only available on Windows!
115+
116+
112117
Using Features From the OS Shell
113118
--------------------------------
114119

components/property_info.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ information from annotations of properties and methods, such as ``@var``,
438438

439439
// Extraction.php
440440
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
441+
use App\Domain\Foo;
441442

442443
$phpStanExtractor = new PhpStanExtractor();
443444
$phpStanExtractor->getTypesFromConstructor(Foo::class, 'bar');
@@ -505,6 +506,31 @@ with the ``property_info`` service in the Symfony Framework::
505506
// Type information.
506507
$doctrineExtractor->getTypes($class, $property);
507508

509+
ConstructorExtractor
510+
~~~~~~~~~~~~~~~~~~~~
511+
512+
The :class:`Symfony\\Component\\PropertyInfo\\Extractor\\ConstructorExtractor`
513+
tries to extract properties information by using either the
514+
:class:`Symfony\\Component\\PropertyInfo\\Extractor\\PhpStanExtractor` or
515+
the :class:`Symfony\\Component\\PropertyInfo\\Extractor\\ReflectionExtractor`
516+
on the constructor arguments::
517+
518+
// src/Domain/Foo.php
519+
class Foo
520+
{
521+
public function __construct(
522+
private string $bar,
523+
) {
524+
}
525+
}
526+
527+
// Extraction.php
528+
use App\Domain\Foo;
529+
use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor;
530+
531+
$constructorExtractor = new ConstructorExtractor([new ReflectionExtractor()]);
532+
$constructorExtractor->getTypes(Foo::class, 'bar')[0]->getBuiltinType(); // returns 'string'
533+
508534
.. _`components-property-information-extractors-creation`:
509535

510536
Creating Your Own Extractors

components/psr7.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ Usage
2929
Converting from HttpFoundation Objects to PSR-7
3030
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3131

32-
The bridge provides an interface of a factory called
33-
:class:`Symfony\\Bridge\\PsrHttpMessage\\HttpMessageFactoryInterface`
34-
that builds objects implementing PSR-7 interfaces from HttpFoundation objects.
32+
The bridge provides an interface of a factory called
33+
`HttpMessageFactoryInterface`_ that builds objects implementing PSR-7
34+
interfaces from HttpFoundation objects.
3535

3636
The following code snippet explains how to convert a :class:`Symfony\\Component\\HttpFoundation\\Request`
3737
to a ``Nyholm\Psr7\ServerRequest`` class implementing the
@@ -66,8 +66,8 @@ Converting Objects implementing PSR-7 Interfaces to HttpFoundation
6666
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6767

6868
On the other hand, the bridge provide a factory interface called
69-
:class:`Symfony\\Bridge\\PsrHttpMessage\\HttpFoundationFactoryInterface`
70-
that builds HttpFoundation objects from objects implementing PSR-7 interfaces.
69+
`HttpFoundationFactoryInterface`_ that builds HttpFoundation objects from
70+
objects implementing PSR-7 interfaces.
7171

7272
The next snippet explain how to convert an object implementing the
7373
``Psr\Http\Message\ServerRequestInterface`` interface to a
@@ -93,3 +93,5 @@ to a :class:`Symfony\\Component\\HttpFoundation\\Response` instance::
9393
.. _`PSR-7`: https://www.php-fig.org/psr/psr-7/
9494
.. _`PSR-17`: https://www.php-fig.org/psr/psr-17/
9595
.. _`libraries that implement psr/http-factory-implementation`: https://packagist.org/providers/psr/http-factory-implementation
96+
.. _`HttpMessageFactoryInterface`: https://github.com/symfony/psr-http-message-bridge/blob/main/HttpMessageFactoryInterface.php
97+
.. _`HttpFoundationFactoryInterface`: https://github.com/symfony/psr-http-message-bridge/blob/main/HttpFoundationFactoryInterface.php

contributing/code/standards.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,14 @@ Structure
179179

180180
* Exception and error message strings must be concatenated using :phpfunction:`sprintf`;
181181

182-
* Exception and error messages must not contain backticks (e.g. 'The \`foo\` option ...'),
182+
* Exception and error messages must not contain backticks,
183183
even when referring to a technical element (such as a method or variable name).
184-
Double quotes must be used at all time (e.g. 'The "foo" option ...'),;
184+
Double quotes must be used at all time:
185+
186+
.. code-block:: diff
187+
188+
- Expected `foo` option to be one of ...
189+
+ Expected "foo" option to be one of ...
185190
186191
* Exception and error messages must start with a capital letter and finish with a dot ``.``;
187192

doctrine/events.rst

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,13 @@ do so, define a listener for the ``postPersist`` Doctrine event::
119119
namespace App\EventListener;
120120

121121
use App\Entity\Product;
122-
use Doctrine\Persistence\Event\LifecycleEventArgs;
122+
use Doctrine\ORM\Event\PostPersistEventArgs;
123123

124124
class SearchIndexer
125125
{
126126
// the listener methods receive an argument which gives you access to
127127
// both the entity object of the event and the entity manager itself
128-
public function postPersist(LifecycleEventArgs $args): void
128+
public function postPersist(PostPersistEventArgs $args): void
129129
{
130130
$entity = $args->getObject();
131131

@@ -140,6 +140,11 @@ do so, define a listener for the ``postPersist`` Doctrine event::
140140
}
141141
}
142142

143+
.. note::
144+
145+
In previous Doctrine versions, instead of ``PostPersistEventArgs``, you had
146+
to use ``LifecycleEventArgs``, which was deprecated in Doctrine ORM 2.14.
147+
143148
Then, add the ``#[AsDoctrineListener]`` attribute to the class to enable it as
144149
a Doctrine listener in your application::
145150

@@ -167,12 +172,12 @@ listener in the Symfony application by creating a new service for it and
167172
namespace App\EventListener;
168173
169174
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
170-
use Doctrine\ORM\Event\LifecycleEventArgs;
175+
use Doctrine\ORM\Event\PostPersistEventArgs;
171176
172177
#[AsDoctrineListener('postPersist'/*, 500, 'default'*/)]
173178
class SearchIndexer
174179
{
175-
public function postPersist(LifecycleEventArgs $event): void
180+
public function postPersist(PostPersistEventArgs $event): void
176181
{
177182
// ...
178183
}
@@ -277,13 +282,13 @@ First, define a PHP class that handles the ``postUpdate`` Doctrine event::
277282
namespace App\EventListener;
278283

279284
use App\Entity\User;
280-
use Doctrine\Persistence\Event\LifecycleEventArgs;
285+
use Doctrine\ORM\Event\PostUpdateEventArgs;
281286

282287
class UserChangedNotifier
283288
{
284289
// the entity listener methods receive two arguments:
285290
// the entity instance and the lifecycle event
286-
public function postUpdate(User $user, LifecycleEventArgs $event): void
291+
public function postUpdate(User $user, PostUpdateEventArgs $event): void
287292
{
288293
// ... do something to notify the changes
289294
}
@@ -419,8 +424,10 @@ want to log all the database activity. To do so, define a subscriber for the
419424

420425
use App\Entity\Product;
421426
use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
427+
use Doctrine\ORM\Event\PostPersistEventArgs;
428+
use Doctrine\ORM\Event\PostRemoveEventArgs;
429+
use Doctrine\ORM\Event\PostUpdateEventArgs;
422430
use Doctrine\ORM\Events;
423-
use Doctrine\Persistence\Event\LifecycleEventArgs;
424431

425432
class DatabaseActivitySubscriber implements EventSubscriberInterface
426433
{
@@ -436,27 +443,25 @@ want to log all the database activity. To do so, define a subscriber for the
436443
}
437444

438445
// callback methods must be called exactly like the events they listen to;
439-
// they receive an argument of type LifecycleEventArgs, which gives you access
446+
// they receive an argument of type Post*EventArgs, which gives you access
440447
// to both the entity object of the event and the entity manager itself
441-
public function postPersist(LifecycleEventArgs $args): void
448+
public function postPersist(PostPersistEventArgs $args): void
442449
{
443-
$this->logActivity('persist', $args);
450+
$this->logActivity('persist', $args->getObject());
444451
}
445452

446-
public function postRemove(LifecycleEventArgs $args): void
453+
public function postRemove(PostRemoveEventArgs $args): void
447454
{
448-
$this->logActivity('remove', $args);
455+
$this->logActivity('remove', $args->getObject());
449456
}
450457

451-
public function postUpdate(LifecycleEventArgs $args): void
458+
public function postUpdate(PostUpdateEventArgs $args): void
452459
{
453-
$this->logActivity('update', $args);
460+
$this->logActivity('update', $args->getObject());
454461
}
455462

456-
private function logActivity(string $action, LifecycleEventArgs $args): void
463+
private function logActivity(string $action, mixed $entity): void
457464
{
458-
$entity = $args->getObject();
459-
460465
// if this subscriber only applies to certain entity types,
461466
// add some code to check the entity type as early as possible
462467
if (!$entity instanceof Product) {
@@ -467,6 +472,11 @@ want to log all the database activity. To do so, define a subscriber for the
467472
}
468473
}
469474

475+
.. note::
476+
477+
In previous Doctrine versions, instead of ``Post*EventArgs`` classes, you had
478+
to use ``LifecycleEventArgs``, which was deprecated in Doctrine ORM 2.14.
479+
470480
If you're using the :ref:`default services.yaml configuration <service-container-services-load-example>`
471481
and DoctrineBundle 2.1 (released May 25, 2020) or newer, this example will already
472482
work! Otherwise, :ref:`create a service <service-container-creating-service>` for this

form/form_collections.rst

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -643,12 +643,8 @@ the relationship between the removed ``Tag`` and ``Task`` object.
643643

644644
class TaskController extends AbstractController
645645
{
646-
public function edit($id, Request $request, EntityManagerInterface $entityManager): Response
646+
public function edit(Task $task, Request $request, EntityManagerInterface $entityManager): Response
647647
{
648-
if (null === $task = $entityManager->getRepository(Task::class)->find($id)) {
649-
throw $this->createNotFoundException('No task found for id '.$id);
650-
}
651-
652648
$originalTags = new ArrayCollection();
653649

654650
// Create an ArrayCollection of the current Tag objects in the database

form/use_empty_data.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ The closure must accept a ``FormInterface`` instance as the first argument::
9494
public function configureOptions(OptionsResolver $resolver): void
9595
{
9696
$resolver->setDefaults([
97-
'empty_data' => function (FormInterface $form) {
97+
'empty_data' => function (FormInterface $form): Blog {
9898
return new Blog($form->get('title')->getData());
9999
},
100100
]);

html_sanitizer.rst

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,73 @@ the HTML sanitizer: ``src``, ``href``, ``lowsrc``, ``background`` and ``ping``.
931931
->allowRelativeMedias()
932932
);
933933
934+
Max Input Length
935+
~~~~~~~~~~~~~~~~
936+
937+
In order to prevent `DoS attacks`_, by default the HTML sanitizer limits the
938+
input length to ``20000`` characters (as measured by ``strlen($input)``). All
939+
the contents exceeding that length will be truncated. Use this option to
940+
increase or decrease this limit:
941+
942+
.. configuration-block::
943+
944+
.. code-block:: yaml
945+
946+
# config/packages/html_sanitizer.yaml
947+
framework:
948+
html_sanitizer:
949+
sanitizers:
950+
app.post_sanitizer:
951+
# ...
952+
953+
# inputs longer (in characters) than this value will be truncated
954+
max_input_length: 30000 # default: 20000
955+
956+
.. code-block:: xml
957+
958+
<!-- config/packages/html_sanitizer.xml -->
959+
<?xml version="1.0" encoding="UTF-8" ?>
960+
<container xmlns="http://symfony.com/schema/dic/services"
961+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
962+
xmlns:framework="http://symfony.com/schema/dic/symfony"
963+
xsi:schemaLocation="http://symfony.com/schema/dic/services
964+
https://symfony.com/schema/dic/services/services-1.0.xsd
965+
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
966+
967+
<framework:config>
968+
<framework:html-sanitizer>
969+
<framework:sanitizer name="app.post_sanitizer">
970+
<!-- inputs longer (in characters) than this value will be truncated (default: 20000) -->
971+
<framework:max-input-length>20000</framework:max-input-length>
972+
</framework:sanitizer>
973+
</framework:html-sanitizer>
974+
</framework:config>
975+
</container>
976+
977+
.. code-block:: php
978+
979+
// config/packages/framework.php
980+
use Symfony\Config\FrameworkConfig;
981+
982+
return static function (FrameworkConfig $framework) {
983+
$framework->htmlSanitizer()
984+
->sanitizer('app.post_sanitizer')
985+
// inputs longer (in characters) than this value will be truncated (default: 20000)
986+
->withMaxInputLength(20000)
987+
;
988+
};
989+
990+
.. code-block:: php-standalone
991+
992+
use Symfony\Component\HtmlSanitizer\HtmlSanitizer;
993+
use Symfony\Component\HtmlSanitizer\HtmlSanitizerConfig;
994+
995+
$postSanitizer = new HtmlSanitizer(
996+
(new HtmlSanitizerConfig())
997+
// inputs longer (in characters) than this value will be truncated (default: 20000)
998+
->withMaxInputLength(20000)
999+
);
1000+
9341001
Custom Attribute Sanitizers
9351002
~~~~~~~~~~~~~~~~~~~~~~~~~~~
9361003

@@ -1013,3 +1080,4 @@ to enable it for an HTML sanitizer:
10131080
10141081
.. _`HTML Sanitizer W3C Standard Proposal`: https://wicg.github.io/sanitizer-api/
10151082
.. _`W3C Standard Proposal`: https://wicg.github.io/sanitizer-api/
1083+
.. _`DoS attacks`: https://en.wikipedia.org/wiki/Denial-of-service_attack

notifier.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The notifier component supports the following channels:
3636
.. tip::
3737

3838
Use :doc:`secrets </configuration/secrets>` to securely store your
39-
API's tokens.
39+
API tokens.
4040

4141
.. _notifier-sms-channel:
4242

profiler.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,27 @@ you'll need to configure the data collector explicitly:
523523
// 'priority' => 300,
524524
]);
525525
};
526+
527+
Conditional Profiling
528+
~~~~~~~~~~~~~~~~~~~~~
529+
530+
Symfony profiler provides an immense amount of debug information to quickly find the cause of any problem. However, that comes at a price, because the profiler must collect all that information while serving the request. This can slowdown the application even for requests where you don't look at the profiler information (which are most of them).
531+
532+
You can enable the profiler conditionally. To do that, add these two new config options:
533+
534+
.. configuration-block::
535+
536+
.. code-block:: yaml
537+
538+
# config/packages/dev/web_profiler.yaml
539+
framework:
540+
profiler:
541+
collect: false
542+
collect_parameter: 'profile'
543+
544+
The collect: false option disables the profiler by default and the collect_parameter: profile option enables it for requests that include the profile query parameter.
545+
546+
You can freely choose the query parameter name and you can also enable the profiler by submitting a form field with that name (useful for POST requests) and even a request attribute.
526547

527548
.. _`Single-page applications`: https://en.wikipedia.org/wiki/Single-page_application
528549
.. _`Blackfire`: https://blackfire.io/docs/introduction?utm_source=symfony&utm_medium=symfonycom_docs&utm_campaign=profiler

security/access_denied_handler.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ unauthenticated user tries to access a protected resource::
3434
class AuthenticationEntryPoint implements AuthenticationEntryPointInterface
3535
{
3636
public function __construct(
37-
UrlGeneratorInterface $urlGenerator,
37+
private UrlGeneratorInterface $urlGenerator,
3838
) {
3939
}
4040

0 commit comments

Comments
 (0)