Ajouter ses propres données à la Timeline du Profiler

Votre application est un peu lente, et vous voulez savoir ce qui prend du temps ? Premier réflexe, aller voir la timeline du profiler en debug mod dans la toolbar de Symfony. Oui mais voilà, votre service n’y apparaît pas, hors il en fait des choses votre service, et peut être que c’est lui le coupable de vos lenteurs ?! Pas de panique, vous pouvez ajouter vos propres temps d’exécutions dans la timeline.

(Version : 2.2, 2.3)

Si vous partez d’une installation fraîche de symfony (standard), la time line sur le helloworld ressemble à ça :

profiler-1

Nous allons ajouter un service SuisseManager un peu lent au bundle AcmeHelloBundle, le service se contente d’attendre un temps aléatoire pour simuler un traitement. L’astuce ici est d’injecter le composant Stopwatcher à notre service pour ensuite démarrer puis arrêter notre propre évènement, ici nommé « SuisseManager::eatChocolate« .

// src/Acme/DemoBundle/Service/SuisseManager.php

namespace Acme\DemoBundle\Service;

use Symfony\Component\Stopwatch\Stopwatch;

class SuisseManager
{
    /**
    * @var Stopwatch
    */
    protected $stopwatch;

    public function __construct(Stopwatch $stopwatch = null)
    {
        $this->stopwatch = $stopwatch;
    }

    public function eatChocolate()
    {
        if ($this->stopwatch) {
            $this->stopwatch->start('SuisseManager::eatChocolate');
        }

        usleep(rand(1000,5000));

        if ($this->stopwatch) {
            $this->stopwatch->stop('SuisseManager::eatChocolate');
        }
    }
}

Comme d’habitude, il faut déclarer le service, et indiquer à l’injecteur de dépendance de passer l’instance du composant Stopwatch de Symfony, qui a pour id « debug.stopwatch« , au constructeur de notre service.

    <service id="acme.suisse_manager" class="Acme\DemoBundle\Service\SuisseManager">
        <argument type="service" id="debug.stopwatch" on-invalid="null" />
    </service>

Or if you prefer YML :

    acme.suisse_manager:
        class: Acme\DemoBundle\Service\SuisseManager
        arguments: [@?debug.stopwatch]

La subtilité ici est de mettre on-invalid= »null » (ou @?service_id en yml) pour rendre l’injection facultative. Ainsi lorsque le service n’est pas disponible (ce qui est le cas en environnement de production), l’injecteur de dépendance passent le paramètre à null.

Il ne reste plus ensuite qu’à utiliser le service, dans cet exemple le service est utilisé à plusieurs reprises et avec un temps entre chaque utilisation.

// src/Acme/DemoBundle/Controller/DemoController
// ...
    public function helloAction($name)
    {
        $this->get('acme.suisse_manager')->eatChocolate();

        usleep(1000);

        $this->get('acme.suisse_manager')->eatChocolate();

        usleep(1000);

        $this->get('acme.suisse_manager')->eatChocolate();

        return array('name' => $name);
    }
// ...

Et cette fois-ci, lorsque nous allons voir du coter de la timeline, notre event est visible :

profiler-2

Versions utilisées: 2.2, 2.3