Skip to content

Commit f1de079

Browse files
committed
Updated the article about data collectors
1 parent 17bb0fc commit f1de079

File tree

1 file changed

+172
-71
lines changed

1 file changed

+172
-71
lines changed

cookbook/profiler/data_collector.rst

Lines changed: 172 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
How to Create a custom Data Collector
55
=====================================
66

7-
:doc:`The Symfony Profiler </cookbook/profiler/index>` delegates data collecting to
8-
data collectors. Symfony comes bundled with a few of them, but you can easily
9-
create your own.
7+
:doc:`The Symfony Profiler </cookbook/profiler/index>` delegates data collection
8+
to some special classes called data collectors. Symfony comes bundled with a few
9+
of them, but you can easily create your own.
1010

1111
Creating a custom Data Collector
1212
--------------------------------
@@ -33,12 +33,12 @@ Creating a custom data collector is as simple as implementing the
3333
function getName();
3434
}
3535

36-
The ``getName()`` method must return a unique name. This is used to access the
37-
information later on (see :doc:`/cookbook/testing/profiling` for
38-
instance).
36+
The value returned by ``getName()`` must be unique in the application. This value
37+
is also used to access the information later on (see :doc:`/cookbook/testing/profiling`
38+
for instance).
3939

40-
The ``collect()`` method is responsible for storing the data it wants to give
41-
access to in local properties.
40+
The ``collect()`` method is responsible for storing the collected data in local
41+
properties.
4242

4343
.. caution::
4444

@@ -51,101 +51,169 @@ Most of the time, it is convenient to extend
5151
populate the ``$this->data`` property (it takes care of serializing the
5252
``$this->data`` property)::
5353

54-
class MemoryDataCollector extends DataCollector
54+
// src/AppBundle/DataCollector/MyCollector.php
55+
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
56+
57+
class MyCollector extends DataCollector
5558
{
5659
public function collect(Request $request, Response $response, \Exception $exception = null)
5760
{
5861
$this->data = array(
59-
'memory' => memory_get_peak_usage(true),
62+
'variable' => 'value',
6063
);
6164
}
6265

63-
public function getMemory()
66+
public function getVariable()
6467
{
65-
return $this->data['memory'];
68+
return $this->data['variable'];
6669
}
6770

6871
public function getName()
6972
{
70-
return 'memory';
73+
return 'app.my_collector';
7174
}
7275
}
7376

7477
.. _data_collector_tag:
7578

76-
Enabling custom Data Collectors
79+
Enabling Custom Data Collectors
7780
-------------------------------
7881

79-
To enable a data collector, add it as a regular service in one of your
80-
configuration, and tag it with ``data_collector``:
82+
To enable a data collector, define it as a regular service and tag it with
83+
``data_collector``:
8184

8285
.. configuration-block::
8386

8487
.. code-block:: yaml
8588
89+
# app/config/services.yml
8690
services:
87-
data_collector.your_collector_name:
88-
class: Fully\Qualified\Collector\Class\Name
91+
app.my_collector:
92+
class: AppBundle\DataCollector\MyCollector
93+
public: false
8994
tags:
9095
- { name: data_collector }
9196
9297
.. code-block:: xml
9398
94-
<service id="data_collector.your_collector_name" class="Fully\Qualified\Collector\Class\Name">
95-
<tag name="data_collector" />
96-
</service>
99+
<!-- app/config/services.xml -->
100+
<?xml version="1.0" encoding="UTF-8" ?>
101+
<container xmlns="http://symfony.com/schema/dic/services"
102+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
103+
xsi:schemaLocation="http://symfony.com/schema/dic/services
104+
http://symfony.com/schema/dic/services/services-1.0.xsd"
105+
>
106+
<services>
107+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector"
108+
public="false">
109+
<tag name="data_collector" />
110+
</service>
111+
</services>
112+
</container>
97113
98114
.. code-block:: php
99115
116+
// app/config/services.php
100117
$container
101-
->register('data_collector.your_collector_name', 'Fully\Qualified\Collector\Class\Name')
118+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
119+
->setPublic(false)
102120
->addTag('data_collector')
103121
;
104122
105123
Adding Web Profiler Templates
106124
-----------------------------
107125

108-
When you want to display the data collected by your data collector in the web
109-
debug toolbar or the web profiler, you will need to create a Twig template. The
110-
following example can help you get started:
126+
The information collected by your data collector can be displayed both in the
127+
web debug toolbar and in the web profiler. To do so, you need to create a Twig
128+
template that includes some specific blocks.
129+
130+
In the simplest case, you just want to display the information in the toolbar
131+
without providing a profiler panel. This requires to define the ``toolbar``
132+
block and set the value of two variables called ``icon`` and ``text``:
111133

112-
.. code-block:: jinja
134+
.. code-block:: html+jinja
113135

114136
{% extends 'WebProfilerBundle:Profiler:layout.html.twig' %}
115137

116138
{% block toolbar %}
117-
{# This toolbar item may appear along the top or bottom of the screen.#}
118139
{% set icon %}
119-
<span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC" alt=""/></span>
120-
<span class="sf-toolbar-status">Example</span>
140+
{# this is the content displayed as a panel in the toolbar #}
141+
<span class="icon"><img src="..." alt=""/></span>
142+
<span class="sf-toolbar-status">Information</span>
121143
{% endset %}
122144

123145
{% set text %}
124-
<div class="sf-toolbar-info-piece">
125-
<b>Quick piece of data</b>
126-
<span>100 units</span>
127-
</div>
128-
<div class="sf-toolbar-info-piece">
129-
<b>Another quick thing</b>
130-
<span>300 units</span>
131-
</div>
146+
{# this is the content displayed when hovering the mouse over
147+
the toolbar panel #}
148+
<div class="sf-toolbar-info-piece">
149+
<b>Quick piece of data</b>
150+
<span>100 units</span>
151+
</div>
152+
<div class="sf-toolbar-info-piece">
153+
<b>Another piece of data</b>
154+
<span>300 units</span>
155+
</div>
132156
{% endset %}
133157

134-
{# Set the "link" value to false if you do not have a big "panel"
135-
section that you want to direct the user to. #}
136-
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
158+
{# the 'link' value set to 'false' means that this panel doesn't
159+
show a section in the web profiler. #}
160+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
161+
{% endblock %}
162+
163+
.. tip::
164+
165+
Built-in collector templates define all their images as embedded base64-encoded
166+
images. This makes them work everywhere without having to mess with web assets
167+
links:
168+
169+
.. code-block:: html
170+
171+
<img src="data:image/png;base64,..." />
172+
173+
Another solution is to define the images as SVG files. In addition to being
174+
resolution-independent, these images can be easily embedded in the Twig
175+
template or included from an external file to reuse them in several templates:
137176

177+
.. code-block:: jinja
178+
179+
{{ include('@App/data_collector/icon.svg') }}
180+
181+
You are encouraged to use the latter technique for your own toolbar panels.
182+
183+
If the toolbar panel includes extended web profiler information, the Twig template
184+
must also define additional blocks:
185+
186+
.. code-block:: html+jinja
187+
188+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
189+
190+
{% block toolbar %}
191+
{% set icon %}
192+
<span class="icon"><img src="..." alt=""/></span>
193+
<span class="sf-toolbar-status">Information</span>
194+
{% endset %}
195+
196+
{% set text %}
197+
<div class="sf-toolbar-info-piece">
198+
{# ... #}
199+
</div>
200+
{% endset %}
201+
202+
{# the 'link' value is now set to 'true', which allows the user to click
203+
on it to access the web profiler panel. Since 'true' is the default
204+
value, you can omit the 'link' parameter entirely #}
205+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true }) }}
138206
{% endblock %}
139207

140208
{% block head %}
141-
{# Optional, if you need your own JS or CSS files. #}
142-
{{ parent() }} {# Use parent() to keep the default styles #}
209+
{# Optional, you can here link to or define your own CSS and JS contents #}
210+
{# {{ parent() }} to keep the default styles #}
143211
{% endblock %}
144212

145213
{% block menu %}
146214
{# This left-hand menu appears when using the full-screen profiler. #}
147215
<span class="label">
148-
<span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC" alt=""/></span>
216+
<span class="icon"><img src="..." alt=""/></span>
149217
<strong>Example Collector</strong>
150218
</span>
151219
{% endblock %}
@@ -158,57 +226,90 @@ following example can help you get started:
158226
</p>
159227
{% endblock %}
160228

161-
Each block is optional. The ``toolbar`` block is used for the web debug
162-
toolbar and ``menu`` and ``panel`` are used to add a panel to the web
163-
profiler.
164-
229+
The ``menu`` and ``panel`` blocks are the only required blocks to define the
230+
contents displayed in the web profiler panel associated with this data collector.
165231
All blocks have access to the ``collector`` object.
166232

167-
.. tip::
233+
Finally, to enable the data collector template, add a ``template`` attribute to
234+
the ``data_collector`` tag in your service configuration:
168235

169-
Built-in templates use a base64 encoded image for the toolbar:
236+
.. configuration-block::
170237

171-
.. code-block:: html
238+
.. code-block:: yaml
172239
173-
<img src="data:image/png;base64,..." />
240+
# app/config/services.yml
241+
services:
242+
app.my_collector:
243+
class: AppBundle\DataCollector\MyCollector
244+
tags:
245+
-
246+
name: data_collector
247+
template: 'data_collector/template.html.twig'
248+
id: 'app.my_collector'
249+
public: false
174250
175-
You can easily calculate the base64 value for an image with this
176-
little script::
251+
.. code-block:: xml
177252
178-
#!/usr/bin/env php
179-
<?php
180-
echo base64_encode(file_get_contents($_SERVER['argv'][1]));
253+
<!-- app/config/services.xml -->
254+
<?xml version="1.0" encoding="UTF-8" ?>
255+
<container xmlns="http://symfony.com/schema/dic/services"
256+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
257+
xsi:schemaLocation="http://symfony.com/schema/dic/services
258+
http://symfony.com/schema/dic/services/services-1.0.xsd"
259+
>
260+
<services>
261+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector">
262+
<tag name="data_collector" template="data_collector/template.html.twig" id="app.my_collector" public="false" />
263+
</service>
264+
</services>
265+
</container>
181266
182-
To enable the template, add a ``template`` attribute to the ``data_collector``
183-
tag in your configuration. For example, assuming your template is in AppBundle:
267+
.. code-block:: php
268+
269+
// app/config/services.php
270+
$container
271+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
272+
->setPublic(false)
273+
->addTag('data_collector', array(
274+
'template' => 'data_collector/template.html.twig',
275+
'id' => 'app.my_collector',
276+
))
277+
;
278+
279+
.. caution::
280+
281+
The ``id`` attribute must match the value returned by the ``getName()`` method.
282+
283+
The position of each panel in the toolbar is determined by the priority defined
284+
by each collector. Most built-in collectors use ``255`` as their priority. If you
285+
want your collector to be displayed before them, use a higher value:
184286

185287
.. configuration-block::
186288

187289
.. code-block:: yaml
188290
291+
# app/config/services.yml
189292
services:
190-
data_collector.your_collector_name:
191-
class: AppBundle\Collector\Class\Name
293+
app.my_collector:
294+
class: AppBundle\DataCollector\MyCollector
192295
tags:
193-
- { name: data_collector, template: "AppBundle:Collector:templatename", id: "your_collector_name" }
296+
- { name: data_collector, template: '...', id: '...', priority: '300' }
194297
195298
.. code-block:: xml
196299
197-
<service id="data_collector.your_collector_name" class="AppBundle\Collector\Class\Name">
198-
<tag name="data_collector" template="AppBundle:Collector:templatename" id="your_collector_name" />
300+
<!-- app/config/services.xml -->
301+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector">
302+
<tag name="data_collector" template="..." id="..." priority="300" />
199303
</service>
200304
201305
.. code-block:: php
202306
307+
// app/config/services.php
203308
$container
204-
->register('data_collector.your_collector_name', 'AppBundle\Collector\Class\Name')
309+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
205310
->addTag('data_collector', array(
206-
'template' => 'AppBundle:Collector:templatename',
207-
'id' => 'your_collector_name',
311+
'template' => '...',
312+
'id' => '...',
313+
'priority' => 300,
208314
))
209315
;
210-
211-
.. caution::
212-
213-
Make sure the ``id`` attribute is the same string you used for the
214-
``getName()`` method.

0 commit comments

Comments
 (0)