Un exemple pour enrichir la debug toolbar et le profiler de Symfony2 à l'aide du DataCollector

La debug toolbar de Symfony est surement l'outil dont je ne peux plus me passer. Dans Symfony2 elle a été améliorée et on peut désormais l'étendre à l'image de Symfony2. Voici un exemple d'utilisation du DataCollector de sf2 pour ajouter des informations dans la debug toolbar et dans le profiler.

J'ai une application qui utilise des programmes que j'appelle via la class Process de Symfony2. L'idée est d'ajouter un bloc dans la debug toolbar qui affiche le nombre d'appels, le temps et le nombre d'appel en erreur. Ensuite dans le profiler de sf2 je veux ajouter une page pour mes programmes qui listera tous les appels avec en detail la ligne de commande exécutée et la réponse du programme.

1. Le logger

Pour commencer, je vais créer une class qui va logger mes appels.

 
<?php
namespace ACME\TestBundle\Logger;
 
use Symfony\Component\Process\Process;
 
class ProgrammLogger 
{
    private $logs = array();
 
    public function start()
    {
        $currentLog = count($this->logs);
        $this->logs[$currentLog] = array('time' => microtime(true));
 
        return $currentLog;
    }
 
    public function stop(Process $process, $logNumber, $onError = false)
    {
        $time = microtime(true) - $this->logs[$logNumber]['time'];
        $this->logs[$logNumber] = array('binaire' => $process->getCommandLine(),
                                        'error' => $onError,
                                        'output' => ($onError)? $process->getErrorOutput() : $process->getOutput(),
                                        'time' => $time);
    }
 
    public function getLogs()
    {
        return $this->logs;
    }
}

Je définis cette classe en tant que service, ce sera plus simple pour y avoir accès et j'aurai besoin de ce service dans mon DataCollector.

 
parameters:
    test_lib.programm_logger.class_name: ACME\TestBundle\Logger\ProgrammLogger
 
services:
    test_lib.programm_logger:
        class: %test_lib.programm_logger.class_name%
 

L'utilisation de la classe et du service est assez simple:

 
public function indexAction()
{
        $programm = new Symfony\Component\Process\Process();
        $programm->setTimeout(10);
        $programm->setCommandLine('/usr/share/local/bin1 -s value1');
 
        $logNbr = $this->get('test_lib.programm_logger')->start();
        try {
            $result = $programm->run();
            $this->get('test_lib.programm_logger')->stop($programm, $logNbr);
        } catch (\RuntimeException) {
            $this->get('test_lib.programm_logger')->stop($programm, $logNbr, true);
        }
}

 

2. Le DataCollector

Maintenant je vais créer le DataCollector, il recevra en argument du constructeur le logger et contiendra les getters qui me permettront d'accéder aux données dans mon template.

 
<?php
namespace Risk\LibBundle\DataCollector;
 
use ACME\TestBundle\Logger\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
 
class ProgrammDataCollector extends DataCollector
{
    private $logger;
 
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
 
    public function collect(Request $request, Response $response, \Exception $exception = null)
    {
        if ($this->logger) {
            $this->data = array('programm' => $this->logger->getLogs());
        } else {
            $this->data = array('programm' => array());
        }
    }
 
    public function getName()
    {
        return 'programm';
    }
 
    public function getNbrCall()
    {
        return count($this->data['programm']);
    }
 
    public function getTotalTime()
    {
        $time = 0;
        foreach ($this->data['programm'] as $call) {
            $time += $call['time'];
        }
 
        return $time;
    }
 
    public function getNbrErrors()
    {
        $errors = 0;
        foreach ($this->data['programm'] as $call) {
            if (true == $call['error']) {
                $errors ++;
            }
        }
        return $errors;
    }
 
    public function getCalls()
    {
        return $this->data['programm'];
    }
}

Il ne reste plus qu'a créer le template qui sera utiliser pour afficher les données.

 
{% extends 'WebProfilerBundle:Profiler:layout.html.twig' %}
 
{% block toolbar %}
    {% set icon %}
        <img width="20" height="28" alt="API" src="data:image/png;base64,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" />
        <span class="sf-toolbar-status{% if collector.nbrerrors > 0 %} sf-toolbar-status-red{% elseif 20 < collector.nbrcall %} sf-toolbar-status-yellow{% endif %}">{{ collector.nbrcall }}</span>
        {% if collector.nbrcall > 0 %}
            <span class="sf-toolbar-info-piece-additional-detail">in {{ '%0.2f'|format(collector.totaltime) }} ms</span>
        {% endif %}
    {% endset %}
    {% set text %}
        <div class="sf-toolbar-info-piece">
            <b>Programms Calls</b>
            <span>{{ collector.nbrcall }}</span>
        </div>
        <div class="sf-toolbar-info-piece">
            <b>Total time</b>
            <span>{{ '%0.2f'|format(collector.totaltime) }} ms</span>
        </div>
 
        <div class="sf-toolbar-info-piece">
            <b>Errors</b>
            <span class="sf-toolbar-status sf-toolbar-status-{{ collector.nbrerrors > 0 ? 'red' : 'green' }}">{{ collector.nbrerrors }}</span>
        </div>
    {% endset %}
    {% include 'WebProfilerBundle:Profiler:toolbar_item.html.twig' with { 'link': profiler_url } %}
{% endblock %}
 
 
{% block menu %}
<span class="label">
    <span class="icon">
      <img alt="Programms" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACHDwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZEsRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTsAIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQdli7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtFehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGXwzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNFhImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH554SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJVgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyCqbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiEj6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhGfDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFpB+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJyeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJCYVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQlnyfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48vvacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0CvpvfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15LWytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AAbWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0zllmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHWztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5sxybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPwYyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmRXVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNmWS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wlxqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33zaEb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2vTqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqbPhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavrXTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxSfNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAwlJREFUSEu1lktOakEQhgsE0QCRiBijBILRGeoCGDFyBe7COMeRLsKJiQtwZBgyImEB7sABRCcK+H4r5/KVqZPmkRtvOLeT4nBOd9Vffz26O3R2duZVq1VJp9Oyvb0tb29v0uv1ZHZ2VjY2NuTj40PGjVAoJIgNdHjPZrPSaDRkampKvr+/ZX19XVZWViR0cHDgTU9PS61Wk8fHR1laWpL393fJ5/NycnIyFuRvH3d2diQWi0k8HhfP8+Ti4kKOjo4kAjKe8MxkMrK6uqqsFhcX1R6eDo9wOCzHx8fSj4bMzMxIp9NRFgwAisWissEu9vb39yXMJB8Zz8/Pcnt7K3d3d/L09OQDAeYKE9FoVEEIMU8bsCDcn5+fftjn5uYkzIQLBMhvgGBtTvF0gbDnChhh6BkQOep2uyoPDw+qO6xka19fXzVkth5jFmqXPesViJ+vry9dRLhMEdBxipYzgFgLG54GZPawaYLOQI4MCOV/ASLUw0BuJHDYZ8RCA7q/v9fCsKSTeFeMPXm6ubnRdVQtYxwjvkWYtNDlcjktSbyBbr1el5eXFz/R9gejpVJJtra2FAB9+pB+xEF0LZeAaDMfHh56l5eXWqaUpHU7yhSEhcStKg1Fv5cAsXl0+b+8vOzbsF5qt9s/O0Or1dLd4OrqamBbGaHyiw+AIThcKBSUANWpQM1mU87Pz2Vzc1MikcgIi1/YH1gC2+vra6Ey19bWtCq16uhkvFhYWJBEIiHJZHJiYSsiN4TUrzpe+EgVBSGkAecNSPuIWFoiWWB7FAsnEexQDGbb7yM+GhsAJxHsuIx0C3JzFETYXGctdD6Q5YgqCUqICEBWaMrofwDZlWAkR9BjuwmKkQGxwwyEjhf2qSCAcHiEkW2qxDMoRtixHA0wspcg2JgN60nONv/gM6AgyxtW3KT29vb0LNOGtTN+kiYd1sXp+fl52d3d/bmyVSoVr3+79Pro3C4Clf6dTu2Wy2UvdHp66nER5PCj6tji3ZPU/tsl052ztUSF8LhXZOY4sVOplN56/wDvCaZ3ejfbmgAAAABJRU5ErkJggg==" />
    </span>
    <strong>Programms</strong>
    <span class="count">
        <span>{{ collector.nbrcall }}</span>
        <span>{{ '%0.0f'|format(collector.totaltime) }} ms</span>
    </span>
</span>
{% endblock %}
 
{% block panel %}
    <h2>Programms Calls</h2>
 
    {% if not collector.nbrcall %}
        <p>
            <em>No calls.</em>
        </p>
    {% else %}
        <ul class="alt">
            {% for i, call in collector.calls %}
                <li class="{{ i is odd ? 'odd' : 'even' }}">
                    <div>
                        <strong>Binaire</strong>: {{ call.binaire }}<br />
                        <strong>Error</strong>: {% if call.error %}true{% else %}false{% endif %}<br />
                        <strong>Output</strong>: {{ call.output }}
                    </div>
                    <small>
                        <strong>Time</strong>: {{ '%0.2f'|format(call.time) }} ms
                    </small>
                </li>
            {% endfor %}
        </ul>
    {% endif %}
 
{% endblock %}
 

Le bloc "toolbar" contient les infos qui seront affichées dans la toolbar. Le bloc "icon" est la partie toujours visible et le bloc "text" es le div qui apparait au survol de la toolbar.
Les blocs "menu" et "panel" sont affiché dans le profiler.

Il ne reste plus qu'à définir mon DataCollector comme service avec le  tag data_collector pour que Symfony puisse l'utiliser.

 
parameters:
    test_lib.programm_logger.class_name: ACME\TestBundle\Logger\ProgrammLogger
    test_lib.programm_data_collector.class_name:  ACME\TestBundle\DataCollector\ProgrammDataCollector
    test_lib.programm_data_collector.template:  "ACMETestBundle:Collector:programm"
 
services:
    Test_lib.programm_logger:
        class: %test_lib.programm_logger.class_name%
 
    test_lib.data_collector:
        class: %test_lib.programm_data_collector.class_name%
        arguments: [@test_lib.programm_logger]
        tags: 
            - { name: data_collector, template: %test_lib.programm_data_collector.template%, id: "programm" }

J'ai maintenant accès aux informations que je désirais dans la debug toolbar:
debug toolbar

 

Cet article a été écris en se basant sur la documentation pour créer un DataCollector. Je trouvais qu'un exemple concret serait pus parlant.

Il n'y aucun commentaire