Add your own data to the Profiler Timeline

Your application is little slow, and you want what takes so long ? First reflex, go see the profiler’s timeline in the Symfony debug toolbar. Nice, but your service isn’t visible in the timeline, and you know your service do lot of work, which could be the reason of your slowness ! No problem, you can easily add its execution time on the timeline.

If you start with a fresh symfony install (standard dist), the timeline on the helloworld action looks like that :

profiler-1

We are first going to create a service called SwissManagerStopwatcherSwissManager::eatChocolate« .

// src/Acme/DemoBundle/Service/SwissManager.php

namespace Acme\DemoBundle\Service;

use Symfony\Component\Stopwatch\Stopwatch;

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

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

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

        usleep(rand(1000,5000));

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

As usual, you have to declare the service, and tell the dependency injector to give it the Stopwatch component instance to our SuisseManager constructor. The stopwatch service has the following id : « debug.stopwatch« .

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

Ou si vous préférez le YML :

    acme.swiss_manager:
        class: Acme\DemoBundle\Service\SwissManager
        arguments: [@?debug.stopwatch]

The subility here, is to add « on-invalid= »null » » (or @?service_id when using yml), to make our injection optional so when to service is not available (typically when in prod environment), the D.I give a null value instead.

Then you just need to use the Stopwatcher service within your own service.

// 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);
    }
// ...

And now, when we check our timeline, we see how long it takes to our SwissManager to eatChocolate.

profiler-2