Completed
Push — 1.1 ( 58a883 )
by Simonas
02:23
created

ElasticsearchProfiler::getQueries()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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