Completed
Push — in-memory-cache2 ( 6ce751...080bd3 )
by André
32:37
created

PersistenceCacheCollector::getCallData()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 1
dl 0
loc 37
rs 8.7057
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the eZ Publish Kernel package.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishDebugBundle\Collector;
10
11
use eZ\Publish\Core\Persistence\Cache\PersistenceLogger;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
15
16
/**
17
 * Data collector listing SPI cache calls.
18
 */
19
class PersistenceCacheCollector extends DataCollector
20
{
21
    /**
22
     * @var PersistenceLogger
23
     */
24
    private $logger;
25
26
    public function __construct(PersistenceLogger $logger)
27
    {
28
        $this->logger = $logger;
29
    }
30
31
    public function collect(Request $request, Response $response, \Exception $exception = null)
32
    {
33
        $this->data = [
34
            'stats' => $this->logger->getStats(),
35
            'calls_logging_enabled' => $this->logger->isCallsLoggingEnabled(),
36
            'calls' => $this->logger->getCalls(),
37
            'cached' => $this->logger->getCached(),
38
            'handlers' => $this->logger->getLoadedUnCachedHandlers(),
39
        ];
40
    }
41
42
    public function getName()
43
    {
44
        return 'ezpublish.debug.persistence';
45
    }
46
47
    /**
48
     * Returns call count.
49
     *
50
     * @deprecaterd since 7.5, use getStats().
51
     *
52
     * @return int
53
     */
54
    public function getCount()
55
    {
56
        return $this->data['stats']['calls'] + $this->data['stats']['misses'];
57
    }
58
59
    /**
60
     * Returns stats on Persistance cache usage.
61
     *
62
     * @since 7.5
63
     *
64
     * @return int[<string>]
0 ignored issues
show
Documentation introduced by
The doc-type int[<string>] could not be parsed: Expected "]" at position 2, but found "<". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
65
     */
66
    public function getStats()
67
    {
68
        return $this->data['stats'];
69
    }
70
71
    /**
72
     * Returns flag to indicate if logging of calls is enabled or not.
73
     *
74
     * Typically not enabled in prod.
75
     *
76
     * @return bool
77
     */
78
    public function getCallsLoggingEnabled()
79
    {
80
        return $this->data['calls_logging_enabled'];
81
    }
82
83
    /**
84
     * Returns all calls.
85
     *
86
     * @return array
87
     */
88
    public function getCalls()
89
    {
90
        return $this->getCallData(array_merge($this->data['calls'], $this->data['cached']));
91
    }
92
93
    private function getCallData(array $data): array
94
    {
95
        if (empty($data)) {
96
            return [];
97
        }
98
99
        $calls = $count = [];
100
        foreach ($data as $call) {
101
            $hash = hash('md5', $call['method'] . implode(',', $call['arguments']));
102
            if (isset($calls[$hash])) {
103
                $calls[$hash]['traces'][$call['hit'] ? 'hit' : 'miss'][] = implode(', ', $call['trace']);
104
                $calls[$hash]['count']++;
105
                $count[$hash]++;
106
107
                continue;
108
            }
109
110
            list($class, $method) = explode('::', $call['method']);
111
            $namespace = explode('\\', $class);
112
            $class = array_pop($namespace);
113
            $calls[$hash] = [
114
                'namespace' => $namespace,
115
                'class' => $class,
116
                'method' => $method,
117
                'arguments' => $this->simplifyCallArguments($call['arguments']),
118
                'traces' => ['miss' => [], 'hit' =>  []],
119
                'count' => 1,
120
            ];
121
            $calls[$hash]['traces'][$call['hit'] ? 'hit' : 'miss'][] = implode(', ', $call['trace']);
122
            $count[$hash] = 1;
123
        }
124
        unset($data);
125
126
        array_multisort($count, SORT_DESC, $calls);
127
128
        return $calls;
129
    }
130
131
    private function simplifyCallArguments(array $arguments): string
132
    {
133
        $string = '';
134
        foreach ($arguments as $key => $value) {
135
            if (!empty($string)) {
136
                $string .= ', ';
137
            }
138
139
            if (!is_numeric($key)) {
140
                $string .= $key . ':';
141
            }
142
143
            if (is_array($value)) {
144
                $string .= '[' . implode(',', $value) . ']';
145
            } else {
146
                $string .= $value;
147
            }
148
        }
149
150
        return $string;
151
    }
152
153
    /**
154
     * Returns un cached handlers being loaded.
155
     *
156
     * @return array
157
     */
158
    public function getHandlers()
159
    {
160
        $handlers = [];
161
        foreach ($this->data['handlers'] as $handler => $count) {
162
            list($class, $method) = explode('::', $handler);
163
            unset($class);
164
            $handlers[$method] = $method . '(' . $count . ')';
165
        }
166
167
        return $handlers;
168
    }
169
170
    /**
171
     * Returns un cached handlers being loaded.
172
     *
173
     * @return array
174
     */
175
    public function getHandlersCount()
176
    {
177
        return array_sum($this->data['handlers']);
178
    }
179
}
180