Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7497f1c

Browse filesBrowse files
Nyholmfabpot
authored andcommitted
Added cache data collector and profiler page
1 parent cc398db commit 7497f1c
Copy full SHA for 7497f1c

File tree

7 files changed

+400
-0
lines changed
Filter options

7 files changed

+400
-0
lines changed
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\Cache\Adapter\TraceableAdapter;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
/**
20+
* Inject a data collector to all the cache services to be able to get detailed statistics.
21+
*
22+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
23+
*/
24+
class CacheCollectorPass implements CompilerPassInterface
25+
{
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function process(ContainerBuilder $container)
30+
{
31+
if (!$container->hasDefinition('data_collector.cache')) {
32+
return;
33+
}
34+
35+
$collectorDefinition = $container->getDefinition('data_collector.cache');
36+
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
37+
if ($container->getDefinition($id)->isAbstract()) {
38+
continue;
39+
}
40+
41+
$container->register($id.'.recorder', TraceableAdapter::class)
42+
->setDecoratedService($id)
43+
->addArgument(new Reference($id.'.recorder.inner'))
44+
->setPublic(false);
45+
46+
// Tell the collector to add the new instance
47+
$collectorDefinition->addMethodCall('addInstance', array($id, new Reference($id)));
48+
}
49+
}
50+
}

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
356356

357357
$loader->load('profiling.xml');
358358
$loader->load('collectors.xml');
359+
$loader->load('cache_debug.xml');
359360

360361
if ($this->formConfigEnabled) {
361362
$loader->load('form_debug.xml');

‎src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
1515
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
1616
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
17+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass;
1718
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
1819
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass;
1920
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass;
@@ -105,6 +106,7 @@ public function build(ContainerBuilder $container)
105106
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
106107
$container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
107108
$container->addCompilerPass(new ConfigCachePass());
109+
$container->addCompilerPass(new CacheCollectorPass());
108110
}
109111
}
110112
}
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<!-- DataCollector -->
9+
<service id="data_collector.cache" class="Symfony\Component\Cache\DataCollector\CacheDataCollector">
10+
<tag name="data_collector" template="@WebProfiler/Collector/cache.html.twig" id="cache" priority="275" />
11+
</service>
12+
</services>
13+
</container>
+146Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
{% extends 'WebProfilerBundle:Profiler:layout.html.twig' %}
2+
3+
{% block toolbar %}
4+
{% if collector.totals.calls > 0 %}
5+
{% set icon %}
6+
{{ include('@WebProfiler/Icon/cache.svg') }}
7+
<span class="sf-toolbar-value">{{ collector.totals.calls }}</span>
8+
<span class="sf-toolbar-info-piece-additional-detail">
9+
<span class="sf-toolbar-label">in</span>
10+
<span class="sf-toolbar-value">{{ '%0.2f'|format(collector.totals.time * 1000) }}</span>
11+
<span class="sf-toolbar-label">ms</span>
12+
</span>
13+
{% endset %}
14+
{% set text %}
15+
<div class="sf-toolbar-info-piece">
16+
<b>Cache Calls</b>
17+
<span>{{ collector.totals.calls }}</span>
18+
</div>
19+
<div class="sf-toolbar-info-piece">
20+
<b>Total time</b>
21+
<span>{{ '%0.2f'|format(collector.totals.time * 1000) }} ms</span>
22+
</div>
23+
<div class="sf-toolbar-info-piece">
24+
<b>Cache hits</b>
25+
<span>{{ collector.totals.hits }}/{{ collector.totals.reads }} ({{ collector.totals['hits/reads'] }})</span>
26+
</div>
27+
<div class="sf-toolbar-info-piece">
28+
<b>Cache writes</b>
29+
<span>{{ collector.totals.writes }}</span>
30+
</div>
31+
{% endset %}
32+
{% include 'WebProfilerBundle:Profiler:toolbar_item.html.twig' with { 'link': profiler_url } %}
33+
{% endif %}
34+
{% endblock %}
35+
36+
{% block menu %}
37+
<span class="label {{ collector.totals.calls == 0 ? 'disabled' }}">
38+
<span class="icon">
39+
{{ include('@WebProfiler/Icon/cache.svg') }}
40+
</span>
41+
<strong>Cache</strong>
42+
<span class="count">
43+
<span>{{ collector.totals.calls }}</span>
44+
<span>{{ '%0.2f'|format(collector.totals.time * 1000) }} ms</span>
45+
</span>
46+
</span>
47+
{% endblock %}
48+
49+
{% block panel %}
50+
<h2>Cache</h2>
51+
<div class="metrics">
52+
<div class="metric">
53+
<span class="value">{{ collector.totals.calls }}</span>
54+
<span class="label">Total calls</span>
55+
</div>
56+
<div class="metric">
57+
<span class="value">{{ '%0.2f'|format(collector.totals.time * 1000) }} ms</span>
58+
<span class="label">Total time</span>
59+
</div>
60+
<div class="metric">
61+
<span class="value">{{ collector.totals.reads }}</span>
62+
<span class="label">Total reads</span>
63+
</div>
64+
<div class="metric">
65+
<span class="value">{{ collector.totals.hits }}</span>
66+
<span class="label">Total hits</span>
67+
</div>
68+
<div class="metric">
69+
<span class="value">{{ collector.totals.misses }}</span>
70+
<span class="label">Total misses</span>
71+
</div>
72+
<div class="metric">
73+
<span class="value">{{ collector.totals.writes }}</span>
74+
<span class="label">Total writes</span>
75+
</div>
76+
<div class="metric">
77+
<span class="value">{{ collector.totals.deletes }}</span>
78+
<span class="label">Total deletes</span>
79+
</div>
80+
<div class="metric">
81+
<span class="value">{{ collector.totals['hits/reads'] }}</span>
82+
<span class="label">Hits/reads</span>
83+
</div>
84+
</div>
85+
86+
{% for name, calls in collector.calls %}
87+
<h3>Statistics for '{{ name }}'</h3>
88+
<div class="metrics">
89+
{% for key, value in collector.statistics[name] %}
90+
<div class="metric">
91+
<span class="value">
92+
{% if key == 'time' %}
93+
{{ '%0.2f'|format(1000*value) }} ms
94+
{% else %}
95+
{{ value }}
96+
{% endif %}
97+
</span>
98+
<span class="label">{{ key|capitalize }}</span>
99+
</div>
100+
{% endfor %}
101+
</div>
102+
<h4>Calls for '{{ name }}'</h4>
103+
104+
{% if not collector.totals.calls %}
105+
<p>
106+
<em>No calls.</em>
107+
</p>
108+
{% else %}
109+
<table>
110+
<thead>
111+
<tr>
112+
<th style="width: 5rem;">Key</th>
113+
<th>Value</th>
114+
</tr>
115+
</thead>
116+
<tbody>
117+
{% for i, call in calls %}
118+
<tr>
119+
<th style="padding-top:2rem">#{{ i }}</th>
120+
<th style="padding-top:2rem">Pool::{{ call.name }}</th>
121+
</tr>
122+
<tr>
123+
<th>Argument</th>
124+
<td>{{ profiler_dump(call.argument, maxDepth=2) }}</td>
125+
</tr>
126+
<tr>
127+
<th>Results</th>
128+
<td>
129+
{% if call.result != false %}
130+
{{ profiler_dump(call.result, maxDepth=1) }}
131+
{% endif %}
132+
</td>
133+
</tr>
134+
<tr>
135+
<th>Time</th>
136+
<td>{{ '%0.2f'|format((call.end - call.start) * 1000) }} ms</td>
137+
</tr>
138+
139+
{% endfor %}
140+
</tbody>
141+
142+
</table>
143+
{% endif %}
144+
{% endfor %}
145+
146+
{% endblock %}
+3Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.