Completed
Pull Request — master (#863)
by
unknown
01:40
created

ElasticsearchProfiler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
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 ONGR\ElasticsearchBundle\Profiler;
13
14
use Monolog\Logger;
15
use ONGR\ElasticsearchBundle\Profiler\Handler\CollectionHandler;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\Response;
18
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
19
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
20
use Symfony\Component\VarDumper\Caster\CutStub;
21
use Symfony\Component\VarDumper\Cloner\Data;
22
use Symfony\Component\VarDumper\Cloner\Stub;
23
use Symfony\Component\VarDumper\Cloner\VarCloner;
24
25
/**
26
 * Data collector for profiling elasticsearch bundle.
27
 */
28
class ElasticsearchProfiler extends DataCollector
29
{
30
    const UNDEFINED_ROUTE = 'undefined_route';
31
32
    /**
33
     * @var Logger[] Watched loggers.
34
     */
35
    private $loggers = [];
36
37
    public function __construct()
38
    {
39
        $this->reset();
40
    }
41
42
    /**
43
     * Adds logger to look for collector handler.
44
     *
45
     * @param Logger $logger
46
     */
47
    public function addLogger(Logger $logger)
48
    {
49
        $this->loggers[] = $logger;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function collect(Request $request, Response $response, \Exception $exception = null)
56
    {
57
        /** @var Logger $logger */
58
        foreach ($this->loggers as $logger) {
59
            foreach ($logger->getHandlers() as $handler) {
60
                if ($handler instanceof CollectionHandler) {
61
                    $this->handleRecords($this->getRoute($request), $handler->getRecords());
62
                    $handler->clearRecords();
63
                }
64
            }
65
        }
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function reset()
72
    {
73
        $this->data = [
74
            'managers' => [],
75
            'queries' => [],
76
            'count' => 0,
77
            'time' => .0,
78
        ];
79
    }
80
81
    /**
82
     * Returns total time queries took.
83
     *
84
     * @return string
85
     */
86
    public function getTime()
87
    {
88
        return round($this->data['time'] * 1000, 2);
89
    }
90
91
    /**
92
     * Returns number of queries executed.
93
     *
94
     * @return int
95
     */
96
    public function getQueryCount()
97
    {
98
        return $this->data['count'];
99
    }
100
101
    /**
102
     * Returns information about executed queries.
103
     *
104
     * Eg. keys:
105
     *      'body'    - Request body.
106
     *      'method'  - HTTP method.
107
     *      'uri'     - Uri request was sent.
108
     *      'time'    - Time client took to respond.
109
     *
110
     * @return array
111
     */
112
    public function getQueries()
113
    {
114
        return $this->cloneVar($this->data['queries']);
115
    }
116
117
    /**
118
     * @return array
119
     */
120
    public function getManagers()
121
    {
122
        $viewManagers = [];
123
        foreach ($this->data['managers'] as $name => $manager) {
124
            $viewManagers[$name] = $this->cloneVar(
125
                $name === 'default'
126
                    ? 'es.manager'
127
                    : sprintf('es.manager.%s', $name)
128
            );
129
        }
130
131
        return $viewManagers;
132
    }
133
134
    /**
135
     * @param array $managers
136
     */
137
    public function setManagers(array $managers)
138
    {
139
        $this->data['managers'] = $managers;
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145
    public function getName()
146
    {
147
        return 'ongr.profiler';
148
    }
149
150
    /**
151
     * Handles passed records.
152
     *
153
     * @param string $route
154
     * @param array  $records
155
     */
156
    private function handleRecords($route, $records)
157
    {
158
        $this->data['count'] += count($records) / 2;
159
        $queryBody = '';
160
        foreach ($records as $record) {
161
            // First record will never have context.
162
            if (!empty($record['context'])) {
163
                $this->data['time'] += $record['context']['duration'];
164
                $this->addQuery($route, $record, $queryBody);
165
            } else {
166
                $position = strpos($record['message'], ' -d');
167
                $queryBody = $position !== false ? substr($record['message'], $position + 3) : '';
168
            }
169
        }
170
    }
171
172
    /**
173
     * Adds query to collected data array.
174
     *
175
     * @param string $route
176
     * @param array  $record
177
     * @param string $queryBody
178
     */
179
    private function addQuery($route, $record, $queryBody)
180
    {
181
        parse_str(parse_url($record['context']['uri'], PHP_URL_QUERY), $httpParameters);
182
        $body = json_decode(trim($queryBody, " '\r\t\n"));
183
        $this->data['queries'][$route][] = array_merge(
184
            [
185
                'body' => $body !== null ? json_encode($body, JSON_PRETTY_PRINT) : '',
186
                'method' => $record['context']['method'],
187
                'httpParameters' => $httpParameters,
188
                'time' => $record['context']['duration'] * 1000,
189
            ],
190
            array_diff_key(parse_url($record['context']['uri']), array_flip(['query']))
191
        );
192
    }
193
194
    /**
195
     * Returns route name from request.
196
     *
197
     * @param Request $request
198
     *
199
     * @return string
200
     */
201
    private function getRoute(Request $request)
202
    {
203
        $route = $request->attributes->get('_route');
204
205
        return empty($route) ? self::UNDEFINED_ROUTE : $route;
206
    }
207
}
208