Completed
Pull Request — master (#863)
by
unknown
19:21
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($name === 'default' ? 'es.manager' : sprintf('es.manager.%s', $name));
125
        }
126
127
        return $viewManagers;
128
    }
129
130
    /**
131
     * @param array $managers
132
     */
133
    public function setManagers(array $managers)
134
    {
135
        $this->data['managers'] = $managers;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public function getName()
142
    {
143
        return 'ongr.profiler';
144
    }
145
146
    /**
147
     * Handles passed records.
148
     *
149
     * @param string $route
150
     * @param array  $records
151
     */
152
    private function handleRecords($route, $records)
153
    {
154
        $this->data['count'] += count($records) / 2;
155
        $queryBody = '';
156
        foreach ($records as $record) {
157
            // First record will never have context.
158
            if (!empty($record['context'])) {
159
                $this->data['time'] += $record['context']['duration'];
160
                $this->addQuery($route, $record, $queryBody);
161
            } else {
162
                $position = strpos($record['message'], ' -d');
163
                $queryBody = $position !== false ? substr($record['message'], $position + 3) : '';
164
            }
165
        }
166
    }
167
168
    /**
169
     * Adds query to collected data array.
170
     *
171
     * @param string $route
172
     * @param array  $record
173
     * @param string $queryBody
174
     */
175
    private function addQuery($route, $record, $queryBody)
176
    {
177
        parse_str(parse_url($record['context']['uri'], PHP_URL_QUERY), $httpParameters);
178
        $body = json_decode(trim($queryBody, " '\r\t\n"));
179
        $this->data['queries'][$route][] = array_merge(
180
            [
181
                'body' => $body !== null ? json_encode($body, JSON_PRETTY_PRINT) : '',
182
                'method' => $record['context']['method'],
183
                'httpParameters' => $httpParameters,
184
                'time' => $record['context']['duration'] * 1000,
185
            ],
186
            array_diff_key(parse_url($record['context']['uri']), array_flip(['query']))
187
        );
188
    }
189
190
    /**
191
     * Returns route name from request.
192
     *
193
     * @param Request $request
194
     *
195
     * @return string
196
     */
197
    private function getRoute(Request $request)
198
    {
199
        $route = $request->attributes->get('_route');
200
201
        return empty($route) ? self::UNDEFINED_ROUTE : $route;
202
    }
203
}
204