Skip to content

Commit 7efe30c

Browse files
committed
Updated the article about data collectors
1 parent bde40f9 commit 7efe30c

File tree

1 file changed

+134
-71
lines changed

1 file changed

+134
-71
lines changed

cookbook/profiler/data_collector.rst

Lines changed: 134 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,119 +33,164 @@ 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

4545
As the profiler serializes data collector instances, you should not
4646
store objects that cannot be serialized (like PDO objects), or you need
4747
to provide your own ``serialize()`` method.
4848

49-
Most of the time, it is convenient to extend
49+
Most of the times, it is convenient to extend
5050
:class:`Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector` and
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+
class MyCollector extends DataCollector
5556
{
5657
public function collect(Request $request, Response $response, \Exception $exception = null)
5758
{
5859
$this->data = array(
59-
'memory' => memory_get_peak_usage(true),
60+
'variable' => 'value',
6061
);
6162
}
6263

63-
public function getMemory()
64+
public function getVariable()
6465
{
65-
return $this->data['memory'];
66+
return $this->data['variable'];
6667
}
6768

6869
public function getName()
6970
{
70-
return 'memory';
71+
return 'app.my_collector';
7172
}
7273
}
7374

7475
.. _data_collector_tag:
7576

76-
Enabling custom Data Collectors
77+
Enabling Custom Data Collectors
7778
-------------------------------
7879

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

8283
.. configuration-block::
8384

8485
.. code-block:: yaml
8586
87+
# app/config/services.yml
8688
services:
87-
data_collector.your_collector_name:
88-
class: Fully\Qualified\Collector\Class\Name
89+
app.my_collector:
90+
class: AppBundle\DataCollector\MyCollector
8991
tags:
9092
- { name: data_collector }
9193
9294
.. code-block:: xml
9395
94-
<service id="data_collector.your_collector_name" class="Fully\Qualified\Collector\Class\Name">
96+
<!-- app/config/services.xml -->
97+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector">
9598
<tag name="data_collector" />
9699
</service>
97100
98101
.. code-block:: php
99102
103+
// app/config/services.php
100104
$container
101-
->register('data_collector.your_collector_name', 'Fully\Qualified\Collector\Class\Name')
105+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
102106
->addTag('data_collector')
103107
;
104108
105109
Adding Web Profiler Templates
106110
-----------------------------
107111

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:
112+
The information collected by your data collector can be displayed both in the
113+
web debug toolbar and in the web profiler. To do so, you need to create a Twig
114+
template that includes some specific blocks.
115+
116+
In the simplest case, you just want to display the information in the toolbar
117+
without providing a profiler panel:
111118

112119
.. code-block:: jinja
113120
114-
{% extends 'WebProfilerBundle:Profiler:layout.html.twig' %}
121+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
115122
116123
{% block toolbar %}
117-
{# This toolbar item may appear along the top or bottom of the screen.#}
118124
{% 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>
125+
<span class="icon"><img src="..." alt=""/></span>
126+
<span class="sf-toolbar-status">Information</span>
121127
{% endset %}
122128
123129
{% 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>
130+
<div class="sf-toolbar-info-piece">
131+
<b>Quick piece of data</b>
132+
<span>100 units</span>
133+
</div>
134+
<div class="sf-toolbar-info-piece">
135+
<b>Another piece of data</b>
136+
<span>300 units</span>
137+
</div>
132138
{% endset %}
133139
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 }) }}
140+
{# the 'link' value set to 'false' means that this panel doesn't show
141+
a section in the web profiler. #}
142+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
143+
{% endblock %}
144+
145+
The ``toolbar`` block is used to create a panel in the web debug toolbar. The
146+
inner ``icon`` block defines the content to display right inside the toolbar
147+
and the ``text`` block defines the content displayed when hovering the mouse
148+
over that same panel.
149+
150+
.. tip::
151+
152+
Built-in collector templates define all their images as embedded base64-encoded
153+
images. This makes them work everywhere without having to mess with web assets
154+
links:
155+
156+
.. code-block:: html
157+
158+
<img src="data:image/png;base64,..." />
159+
160+
You are encouraged to use this same technique for your own toolbar panels.
161+
162+
If the toolbar panel includes extended web profiler information, the Twig template
163+
must also define other blocks:
137164

165+
.. code-block:: jinja
166+
167+
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
168+
169+
{% block toolbar %}
170+
{% set icon %}
171+
<span class="icon"><img src="..." alt=""/></span>
172+
<span class="sf-toolbar-status">Information</span>
173+
{% endset %}
174+
175+
{% set text %}
176+
<div class="sf-toolbar-info-piece">
177+
{# ... #}
178+
</div>
179+
{% endset %}
180+
181+
{# the 'link' value is now set to 'true', which allows the user to click
182+
on it to access to the web profiler panel. #}
183+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true }) }}
138184
{% endblock %}
139185
140186
{% block head %}
141-
{# Optional, if you need your own JS or CSS files. #}
142-
{{ parent() }} {# Use parent() to keep the default styles #}
187+
{# Optional, here you can link to or define your own CSS and JS contents #}
143188
{% endblock %}
144189
145190
{% block menu %}
146191
{# This left-hand menu appears when using the full-screen profiler. #}
147192
<span class="label">
148-
<span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC" alt=""/></span>
193+
<span class="icon"><img src="..." alt=""/></span>
149194
<strong>Example Collector</strong>
150195
</span>
151196
{% endblock %}
@@ -158,58 +203,76 @@ following example can help you get started:
158203
</p>
159204
{% endblock %}
160205
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-
206+
The ``menu`` and ``panel`` blocks are the only required blocks to define the
207+
contents displayed in the web profiler panel associated with this data collector.
165208
All blocks have access to the ``collector`` object.
166209

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

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

171-
.. code-block:: html
215+
.. code-block:: yaml
172216
173-
<img src="data:image/png;base64,..." />
217+
# app/config/services.yml
218+
services:
219+
app.my_collector:
220+
class: AppBundle\DataCollector\MyCollector
221+
tags:
222+
- { name: data_collector, template: 'data_collector/template.html.twig', id: 'app.my_collector' }
223+
224+
.. code-block:: xml
225+
226+
<!-- app/config/services.xml -->
227+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector">
228+
<tag name="data_collector" template="data_collector/template.html.twig" id="app.my_collector" />
229+
</service>
174230
175-
You can easily calculate the base64 value for an image with this
176-
little script::
231+
.. code-block:: php
177232
178-
#!/usr/bin/env php
179-
<?php
180-
echo base64_encode(file_get_contents($_SERVER['argv'][1]));
233+
// app/config/services.php
234+
$container
235+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
236+
->addTag('data_collector', array(
237+
'template' => 'data_collector/template.html.twig',
238+
'id' => 'app.my_collector',
239+
))
240+
;
181241
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 some
184-
AcmeDebugBundle:
242+
.. caution::
243+
244+
The ``id`` attribute must match the value returned by the ``getName()`` method.
245+
246+
The position of each panel in the toolbar is determined by the priority defined
247+
by each collector. Most built-in collectors use ``255`` as their priority. If you
248+
want your collector to be displayed before them, use a higher value:
185249

186250
.. configuration-block::
187251

188252
.. code-block:: yaml
189253
254+
# app/config/services.yml
190255
services:
191-
data_collector.your_collector_name:
192-
class: Acme\DebugBundle\Collector\Class\Name
256+
app.my_collector:
257+
class: AppBundle\DataCollector\MyCollector
193258
tags:
194-
- { name: data_collector, template: "AcmeDebugBundle:Collector:templatename", id: "your_collector_name" }
259+
- { name: data_collector, template: '...', id: '...', priority: '300' }
195260
196261
.. code-block:: xml
197262
198-
<service id="data_collector.your_collector_name" class="Acme\DebugBundle\Collector\Class\Name">
199-
<tag name="data_collector" template="AcmeDebugBundle:Collector:templatename" id="your_collector_name" />
263+
<!-- app/config/services.xml -->
264+
<service id="app.my_collector" class="AppBundle\DataCollector\MyCollector">
265+
<tag name="data_collector" template="..." id="..." priority="300" />
200266
</service>
201267
202268
.. code-block:: php
203269
270+
// app/config/services.php
204271
$container
205-
->register('data_collector.your_collector_name', 'Acme\DebugBundle\Collector\Class\Name')
272+
->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
206273
->addTag('data_collector', array(
207-
'template' => 'AcmeDebugBundle:Collector:templatename',
208-
'id' => 'your_collector_name',
274+
'template' => '...',
275+
'id' => '...',
276+
'priority' => 300,
209277
))
210278
;
211-
212-
.. caution::
213-
214-
Make sure the ``id`` attribute is the same string you used for the
215-
``getName()`` method.

0 commit comments

Comments
 (0)