Completed
Push — master ( 7f2a01...44feb9 )
by
unknown
06:18 queued 04:12
created

DataCollector/DoctrineDataCollector.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle\DataCollector;
4
5
use Doctrine\Common\Persistence\ManagerRegistry;
6
use Doctrine\ORM\Cache\Logging\CacheLoggerChain;
7
use Doctrine\ORM\Cache\Logging\StatisticsCacheLogger;
8
use Doctrine\ORM\Configuration;
9
use Doctrine\ORM\Mapping\ClassMetadataFactory;
10
use Doctrine\ORM\Tools\SchemaValidator;
11
use Doctrine\ORM\Version;
12
use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector as BaseCollector;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\Response;
15
16
/**
17
 * DoctrineDataCollector.
18
 */
19
class DoctrineDataCollector extends BaseCollector
20
{
21
    /** @var ManagerRegistry */
22
    private $registry;
23
24
    /** @var int|null */
25
    private $invalidEntityCount;
26
27
    public function __construct(ManagerRegistry $registry)
28
    {
29
        $this->registry = $registry;
30
31
        parent::__construct($registry);
32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function collect(Request $request, Response $response, \Exception $exception = null)
38
    {
39
        parent::collect($request, $response, $exception);
40
41
        $errors   = [];
42
        $entities = [];
43
        $caches   = [
44
            'enabled' => false,
45
            'log_enabled' => false,
46
            'counts' => [
47
                'puts' => 0,
48
                'hits' => 0,
49
                'misses' => 0,
50
            ],
51
            'regions' => [
52
                'puts' => [],
53
                'hits' => [],
54
                'misses' => [],
55
            ],
56
        ];
57
58
        foreach ($this->registry->getManagers() as $name => $em) {
59
            $entities[$name] = [];
60
            /** @var ClassMetadataFactory $factory */
61
            $factory   = $em->getMetadataFactory();
62
            $validator = new SchemaValidator($em);
63
64
            /** @var $class \Doctrine\ORM\Mapping\ClassMetadataInfo */
65
            foreach ($factory->getLoadedMetadata() as $class) {
66
                if (isset($entities[$name][$class->getName()])) {
67
                    continue;
68
                }
69
70
                $classErrors                        = $validator->validateClass($class);
71
                $entities[$name][$class->getName()] = $class->getName();
72
73
                if (empty($classErrors)) {
74
                    continue;
75
                }
76
77
                $errors[$name][$class->getName()] = $classErrors;
78
            }
79
80
            if (version_compare(Version::VERSION, '2.5.0-DEV') < 0) {
81
                continue;
82
            }
83
84
            /** @var Configuration $emConfig */
85
            $emConfig   = $em->getConfiguration();
86
            $slcEnabled = $emConfig->isSecondLevelCacheEnabled();
87
88
            if (! $slcEnabled) {
89
                continue;
90
            }
91
92
            $caches['enabled'] = true;
93
94
            /** @var $cacheConfiguration \Doctrine\ORM\Cache\CacheConfiguration */
95
            /** @var CacheLoggerChain $cacheLoggerChain */
96
            $cacheConfiguration = $emConfig->getSecondLevelCacheConfiguration();
97
            $cacheLoggerChain   = $cacheConfiguration->getCacheLogger();
98
99
            if (! $cacheLoggerChain || ! $cacheLoggerChain->getLogger('statistics')) {
100
                continue;
101
            }
102
103
            /** @var StatisticsCacheLogger $cacheLoggerStats */
104
            $cacheLoggerStats      = $cacheLoggerChain->getLogger('statistics');
105
            $caches['log_enabled'] = true;
106
107
            $caches['counts']['puts']   += $cacheLoggerStats->getPutCount();
108
            $caches['counts']['hits']   += $cacheLoggerStats->getHitCount();
109
            $caches['counts']['misses'] += $cacheLoggerStats->getMissCount();
110
111 View Code Duplication
            foreach ($cacheLoggerStats->getRegionsPut() as $key => $value) {
112
                if (! isset($caches['regions']['puts'][$key])) {
113
                    $caches['regions']['puts'][$key] = 0;
114
                }
115
116
                $caches['regions']['puts'][$key] += $value;
117
            }
118
119 View Code Duplication
            foreach ($cacheLoggerStats->getRegionsHit() as $key => $value) {
120
                if (! isset($caches['regions']['hits'][$key])) {
121
                    $caches['regions']['hits'][$key] = 0;
122
                }
123
124
                $caches['regions']['hits'][$key] += $value;
125
            }
126
127 View Code Duplication
            foreach ($cacheLoggerStats->getRegionsMiss() as $key => $value) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
                if (! isset($caches['regions']['misses'][$key])) {
129
                    $caches['regions']['misses'][$key] = 0;
130
                }
131
132
                $caches['regions']['misses'][$key] += $value;
133
            }
134
        }
135
136
        // HttpKernel < 3.2 compatibility layer
137
        if (method_exists($this, 'cloneVar')) {
138
            // Might be good idea to replicate this block in doctrine bridge so we can drop this from here after some time.
139
            // This code is compatible with such change, because cloneVar is supposed to check if input is already cloned.
140
            foreach ($this->data['queries'] as &$queries) {
141
                foreach ($queries as &$query) {
142
                    $query['params'] = $this->cloneVar($query['params']);
143
                }
144
            }
145
        }
146
147
        $this->data['entities'] = $entities;
148
        $this->data['errors']   = $errors;
149
        $this->data['caches']   = $caches;
150
    }
151
152
    public function getEntities()
153
    {
154
        return $this->data['entities'];
155
    }
156
157
    public function getMappingErrors()
158
    {
159
        return $this->data['errors'];
160
    }
161
162
    public function getCacheHitsCount()
163
    {
164
        return $this->data['caches']['counts']['hits'];
165
    }
166
167
    public function getCachePutsCount()
168
    {
169
        return $this->data['caches']['counts']['puts'];
170
    }
171
172
    public function getCacheMissesCount()
173
    {
174
        return $this->data['caches']['counts']['misses'];
175
    }
176
177
    public function getCacheEnabled()
178
    {
179
        return $this->data['caches']['enabled'];
180
    }
181
182
    public function getCacheRegions()
183
    {
184
        return $this->data['caches']['regions'];
185
    }
186
187
    public function getCacheCounts()
188
    {
189
        return $this->data['caches']['counts'];
190
    }
191
192
    public function getInvalidEntityCount()
193
    {
194
        if ($this->invalidEntityCount === null) {
195
            $this->invalidEntityCount = array_sum(array_map('count', $this->data['errors']));
196
        }
197
198
        return $this->invalidEntityCount;
199
    }
200
201
    public function getGroupedQueries()
202
    {
203
        static $groupedQueries = null;
204
205
        if ($groupedQueries !== null) {
206
            return $groupedQueries;
207
        }
208
209
        $groupedQueries   = [];
210
        $totalExecutionMS = 0;
211
        foreach ($this->data['queries'] as $connection => $queries) {
212
            $connectionGroupedQueries = [];
213
            foreach ($queries as $i => $query) {
214
                $key = $query['sql'];
215
                if (! isset($connectionGroupedQueries[$key])) {
216
                    $connectionGroupedQueries[$key]                = $query;
217
                    $connectionGroupedQueries[$key]['executionMS'] = 0;
218
                    $connectionGroupedQueries[$key]['count']       = 0;
219
                    $connectionGroupedQueries[$key]['index']       = $i; // "Explain query" relies on query index in 'queries'.
220
                }
221
                $connectionGroupedQueries[$key]['executionMS'] += $query['executionMS'];
222
                $connectionGroupedQueries[$key]['count']++;
223
                $totalExecutionMS += $query['executionMS'];
224
            }
225
            usort($connectionGroupedQueries, function ($a, $b) {
226
                if ($a['executionMS'] === $b['executionMS']) {
227
                    return 0;
228
                }
229
                return ($a['executionMS'] < $b['executionMS']) ? 1 : -1;
230
            });
231
            $groupedQueries[$connection] = $connectionGroupedQueries;
232
        }
233
234
        foreach ($groupedQueries as $connection => $queries) {
235
            foreach ($queries as $i => $query) {
236
                $groupedQueries[$connection][$i]['executionPercent'] =
237
                    $this->executionTimePercentage($query['executionMS'], $totalExecutionMS);
238
            }
239
        }
240
241
        return $groupedQueries;
242
    }
243
244
    private function executionTimePercentage($executionTimeMS, $totalExecutionTimeMS)
245
    {
246
        if ($totalExecutionTimeMS === 0.0 || $totalExecutionTimeMS === 0) {
247
            return 0;
248
        }
249
250
        return $executionTimeMS / $totalExecutionTimeMS * 100;
251
    }
252
253
    public function getGroupedQueryCount()
254
    {
255
        $count = 0;
256
        foreach ($this->getGroupedQueries() as $connectionGroupedQueries) {
257
            $count += count($connectionGroupedQueries);
258
        }
259
260
        return $count;
261
    }
262
}
263