10000 [DoctrineMongoDBBundle] made queries in profiler look like mongodb js… · jaimesuez/symfony@ec46c6e · GitHub
[go: up one dir, main page]

Skip to content

Commit ec46c6e

Browse files
committed
[DoctrineMongoDBBundle] made queries in profiler look like mongodb js shell code
1 parent d59676f commit ec46c6e

File tree

1 file changed

+173
-33
lines changed

1 file changed

+173
-33
lines changed

src/Symfony/Bundle/DoctrineMongoDBBundle/Logger/DoctrineMongoDBLogger.php

Lines changed: 173 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,72 +12,212 @@
1212
namespace Symfony\Bundle\DoctrineMongoDBBundle\Logger;
1313

1414
use Symfony\Component\HttpKernel\Log\LoggerInterface;
15-
use Symfony\Component\Yaml\Yaml;
1615

1716
/**
1817
* Logger for the Doctrine MongoDB ODM.
1918
*
19+
* The {@link logQuery()} method is configured as the logger callable in the
20+
* service container.
21+
*
2022
* @author Kris Wallsmith <kris.wallsmith@symfony.com>
2123
*/
2224
class DoctrineMongoDBLogger
2325
{
24-
const LOG_PREFIX = 'MongoDB query: ';
25-
2626
protected $logger;
27-
protected $nbQueries;
2827

29-
public function __construct(LoggerInterface $logger = null)
28+
protected $prefix;
29+
protected $queries;
30+
31+
protected $processed;
32+
protected $formattedQueries;
33+
protected $nbRealQueries;
34+
35+
/**
36+
* Constructor.
37+
*
38+
* @param LoggerInterface $logger The Symfony logger
39+
* @param string $prefix A prefix for messages sent to the Symfony logger
40+
*/
41+
public function __construct(LoggerInterface $logger = null, $prefix = 'MongoDB query: ')
3042
{
3143
$this->logger = $logger;
32-
$this->nbQueries = 0;
44+
$this->prefix = $prefix;
45+
$this->queries = array();
46+
$this->processed = false;
3347
}
3448

49+
/**
50+
* Logs a query.
51+
*
52+
* This method is configured as the logger callable in the service
53+
* container.
54+
*
55+
* @param array $query A query log array from Doctrine
56+
*/
3557
public function logQuery($query)
3658
{
37-
++$this->nbQueries;
59+
$this->queries[] = $query;
60+
$this->processed = false;
3861

3962
if (null !== $this->logger) {
40-
$this->logger->info(static::LOG_PREFIX.static::formatQuery($query));
63+
$this->logger->info($this->prefix.static::bsonEncode($query));
4164
}
4265
}
4366

67+
/**
68+
* Returns the number of queries that have been logged.
69+
*
70+
* @return integer The number of queries logged
71+
*/
4472
public function getNbQueries()
4573
{
46-
return $this->nbQueries;
74+
if (!$this->processed) {
75+
$this->processQueries();
76+
}
77+
78+
return $this->nbRealQueries;
4779
}
4880

81+
/**
82+
* Returns a human-readable array of queries logged.
83+
*
84+
* @return array An array of queries
85+
*/
4986
public function getQueries()
5087
{
51-
if (null === $this->logger) {
52-
return false;
88+
if (!$this->processed) {
89+
$this->processQueries();
5390
}
5491

55-
$logger = $this->logger->getDebugLogger();
56-
57-
if (!$logger) {
58-
return false;
59-
}
60-
61-
$offset = strlen(static::LOG_PREFIX);
62-
$mapper = function($log) use($offset)
63-
{
64-
if (0 === strpos($log['message'], DoctrineMongoDBLogger::LOG_PREFIX)) {
65-
return substr($log['message'], $offset);
66-
}
67-
};
68-
69-
// map queries from logs, remove empty entries and re-index the array
70-
return array_values(array_filter(array_map($mapper, $logger->getLogs())));
92+
return $this->formattedQueries;
7193
}
7294

7395
/**
74-
* Formats the supplied query array recursively.
96+
* Groups and formats query arrays.
7597
*
76-
* @param array $query All or part of a query array
98+
* @param array $queries An array of query arrays
7799
*
78-
* @return string A serialized object for the log
100+
* @return array An array of human-readable queries
79101
*/
80-
static protected function formatQuery(array $query, $array = true)
102+
protected function processQueries()
103+
{
104+
$this->formattedQueries = array();
105+
$this->nbRealQueries = 0;
106+
107+
$grouped = array();
108+
$ordered = array();
109+
foreach ($this->queries as $query) {
110+
$cursor = serialize($query['query']).serialize($query['fields']);
111+
112+
// append if issued from cursor (currently just "sort")
113+
if (isset($query['sort'])) {
114+
unset($query['query'], $query['fields']);
115+
$grouped[$cursor][count($grouped[$cursor]) - 1][] = $query;
116+
} else {
117+
$grouped[$cursor][] = array($query);
118+
$ordered[] =& $grouped[$cursor][count($grouped[$cursor]) - 1];
119+
}
120+
}
121+
122+
$i = 0;
123+
$db = '';
124+
$query = '';
125+
foreach ($ordered as $logs) {
126+
foreach ($logs as $log) {
127+
if (isset($log['db']) && $db != $log['db']) {
128+
// for readability
129+
$this->formattedQueries[$i++] = 'use '.$log['db'].';';
130+
$db = $log['db'];
131+
}
132+
133+
if (isset($log['collection'])) {
134+
// flush the previous and start a new query
135+
if (!empty($query)) {
136+
if ('.' == $query[0]) {
137+
$query = 'db'.$query;
138+
}
139+
140+
$this->formattedQueries[$i++] = $query.';';
141+
++$this->nbRealQueries;
142+
}
143+
144+
$query = 'db.'.$log['collection'];
145+
}
146+
147+
// format the method call
148+
if (isset($log['authenticate'])) {
149+
$query .= '.authenticate()';
150+
} elseif (isset($log['batchInsert'])) {
151+
$query .= '.batchInsert(**'.$log['num'].' item(s)**)';
152+
} elseif (isset($log['command'])) {
153+
$query .= '.command()';
154+
} elseif (isset($log['count'])) {
155+
$query .= '.count(';
156+
if ($log['query'] || $log['limit'] || $log['skip']) {
157+
$query .= static::bsonEncode($log['query']);
158+
if ($log['limit'] || $log['skip']) {
159+
$query .= ', '.static::bsonEncode($log['limit']);
160+
if ($log['skip']) {
161+
$query .= ', '.static::bsonEncode($log['skip']);
162+
}
163+
}
164+
}
165+
$query .= ')';
166+
} elseif (isset($log['createCollection'])) {
167+
$query .= '.createCollection()';
168+
} elseif (isset($log['createDBRef'])) {
169+
$query .= '.createDBRef()';
170+
} elseif (isset($log['deleteIndex'])) {
171+
$query .= '.dropIndex('.static::bsonEncode($log['keys']).')';
172+
} elseif (isset($log['deleteIndexes'])) {
173+
$query .= '.dropIndexes()';
174+
} elseif (isset($log['drop'])) {
175+
$query .= '.drop()';
176+
} elseif (isset($log['dropDatabase'])) {
177+
$query .= '.dropDatabase()';
178+
} elseif (isset($log['ensureIndex'])) {
179+
$query .= '.ensureIndex('.static::bsonEncode($log['keys']).', '.static::bsonEncode($log['options']).')';
180+
} elseif (isset($log['execute'])) {
181+
$query .= '.execute()';
182+
} elseif (isset($log['find'])) {
183+
$query .= '.find('.static::bsonEncode($log['query']);
184+
if (!empty($log['fields'])) {
185+
$query .= ', '.static::bsonEncode($log['fields']);
186+
}
187+
$query .= ')';
188+
} elseif (isset($log['findOne'])) {
189+
$query .= '.findOne('.static::bsonEncode($log['query']);
190+
if (!empty($log['fields'])) {
191+
$query .= ', '.static::bsonEncode($log['fields']);
192+
}
193+
$query .= ')';
194+
} elseif (isset($log['getDBRef'])) {
195+
$query .= '.getDBRef()';
196+
} elseif (isset($log['group'])) {
197+
$query .= '.group('.static::bsonEncode(array(
198+
'keys' => $log['keys'],
199+
'initial' => $log['initial'],
200+
'reduce' => $log['reduce'],
201+
)).')';
202+
} elseif (isset($log['insert'])) {
203+
$query .= '.insert('.static::bsonEncode($log['document']).')';
204+
} elseif (isset($log['remove'])) {
205+
$query .= '.remove('.static::bsonEncode($log['query']).')';
206+
} elseif (isset($log['save'])) {
207+
$query .= '.save('.static::bsonEncode($log['document']).')';
208+
} elseif (isset($log['sort'])) {
209+
$query .= '.sort('.static::bsonEncode($log['sortFields']).')';
210+
} elseif (isset($log['update'])) {
211+
// todo: include $log['options']
212+
$query .= '.update('.static::bsonEncode($log['query']).', '.static::bsonEncode($log['newObj']).')';
213+
} elseif (isset($log['validate'])) {
214+
$query .= '.validate()';
215+
}
216+
}
217+
}
218+
}
219+
220+
static protected function bsonEncode($query, $array = true)
81221
{
82222
$parts = array();
83223

@@ -91,7 +231,7 @@ static protected function formatQuery(array $query, $array = true)
91231
} elseif (is_scalar($value)) {
92232
$formatted = '"'.$value.'"';
93233
} elseif (is_array($value)) {
94-
$formatted = static::formatQuery($value);
234+
$formatted = static::bsonEncode($value);
95235
} elseif ($value instanceof \MongoId) {
96236
$formatted = 'ObjectId("'.$value.'")';
97237
} elseif ($value instanceof \MongoDate) {
@@ -107,7 +247,7 @@ static protected function formatQuery(array $query, $array = true)
107247
} elseif ($value instanceof \MongoBinData) {
108248
$formatted = 'new BinData("'.$value->bin.'", "'.$value->type.'")';
109249
} elseif ($value instanceof \stdClass) {
110-
$formatted = static::formatQuery((array) $value, false);
250+
$formatted = static::bsonEncode((array) $value);
111251
} else {
112252
$formatted = (string) $value;
113253
}

0 commit comments

Comments
 (0)
0