Better query logging capabilities - implementation #153
Changes from all commits
9315437
4ae21a1
c9f8c97
850f82d
35faf6e
715a1f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,11 @@ class LoggableCollection extends Collection implements Loggable | |
*/ | ||
protected $loggerCallable; | ||
|
||
/** | ||
* @var Logging\QueryLogger | ||
*/ | ||
protected $queryLogger; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
|
@@ -45,13 +50,15 @@ class LoggableCollection extends Collection implements Loggable | |
* @param EventManager $evm EventManager instance | ||
* @param integer $numRetries Number of times to retry queries | ||
* @param callable $loggerCallable The logger callable | ||
* @param Logging\QueryLogger $queryLogger The QueryLogger object | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as earlier regarding a |
||
*/ | ||
public function __construct(Database $database, \MongoCollection $mongoCollection, EventManager $evm, $numRetries, $loggerCallable) | ||
public function __construct(Database $database, \MongoCollection $mongoCollection, EventManager $evm, $numRetries, $loggerCallable = null, Logging\QueryLogger $queryLogger = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jwage: I'm worried about adding more constructor arguments here, since it's a change that then has to be implemented whenever we extend the class (to ensure we accept the argument with the same default value, and then pass it along to the parent). Assuming we allow both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense to me. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'll move it to a setter but best solution would be to remove everything starting at $numRetries and just inject the configuration object so future config params will not be injected seperate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. This is something I've thought about for a while. I changed the constructor order of some of these core classes for |
||
{ | ||
if ( ! is_callable($loggerCallable)) { | ||
throw new \InvalidArgumentException('$loggerCallable must be a valid callback'); | ||
if ( ! is_callable($loggerCallable) && !($queryLogger instanceof Logging\QueryLogger)) { | ||
throw new \InvalidArgumentException('$loggerCallable must be a valid callback or $queryLogger must be an instance of Doctrine\MongoDB\Logging\QueryLogger'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're already type-hinting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, just saw the |
||
} | ||
$this->loggerCallable = $loggerCallable; | ||
$this->queryLogger = $queryLogger; | ||
parent::__construct($database, $mongoCollection, $evm, $numRetries); | ||
} | ||
|
||
|
@@ -65,211 +72,269 @@ public function log(array $log) | |
{ | ||
$log['db'] = $this->database->getName(); | ||
$log['collection'] = $this->getName(); | ||
call_user_func_array($this->loggerCallable, array($log)); | ||
if ($this->loggerCallable) { | ||
call_user_func_array($this->loggerCallable, array($log)); | ||
} | ||
|
||
if ($this->queryLogger instanceof Logging\QueryLogger) { | ||
$this->queryLogger->startQuery($log); | ||
} | ||
} | ||
|
||
private function logAfter() | ||
{ | ||
if ($this->queryLogger instanceof Logging\QueryLogger) { | ||
$this->queryLogger->stopQuery(); | ||
} | ||
} | ||
|
||
/** | ||
* @see Collection::batchInsert() | ||
*/ | ||
public function batchInsert(array &$a, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'batchInsert' => true, | ||
'num' => count($a), | ||
'data' => $a, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::batchInsert($a, $options); | ||
$this->log($log); | ||
$data = parent::batchInsert($a, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::count() | ||
*/ | ||
public function count(array $query = array(), $limit = 0, $skip = 0) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'count' => true, | ||
'query' => $query, | ||
'limit' => $limit, | ||
'skip' => $skip, | ||
)); | ||
); | ||
|
||
return parent::count($query, $limit, $skip); | ||
$this->log($log); | ||
$data = parent::count($query, $limit, $skip); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::deleteIndex() | ||
*/ | ||
public function deleteIndex($keys) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'deleteIndex' => true, | ||
'keys' => $keys, | ||
)); | ||
); | ||
|
||
return parent::deleteIndex($keys); | ||
$this->log($log); | ||
$data = parent::deleteIndex($keys); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::deleteIndexes() | ||
*/ | ||
public function deleteIndexes() | ||
{ | ||
$this->log(array('deleteIndexes' => true)); | ||
$log = array('deleteIndexes' => true); | ||
|
||
return parent::deleteIndexes(); | ||
$this->log($log); | ||
$data = parent::deleteIndexes(); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::drop() | ||
*/ | ||
public function drop() | ||
{ | ||
$this->log(array('drop' => true)); | ||
$log = array('drop' => true); | ||
|
||
return parent::drop(); | ||
$this->log($log); | ||
$data = parent::drop(); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::ensureIndex() | ||
*/ | ||
public function ensureIndex(array $keys, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'ensureIndex' => true, | ||
'keys' => $keys, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::ensureIndex($keys, $options); | ||
$this->log($log); | ||
$data = parent::ensureIndex($keys, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::find() | ||
*/ | ||
public function find(array $query = array(), array $fields = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'find' => true, | ||
'query' => $query, | ||
'fields' => $fields, | ||
)); | ||
); | ||
|
||
return parent::find($query, $fields); | ||
$this->log($log); | ||
$data = parent::find($query, $fields); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::findOne() | ||
*/ | ||
public function findOne(array $query = array(), array $fields = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'findOne' => true, | ||
'query' => $query, | ||
'fields' => $fields, | ||
)); | ||
); | ||
|
||
return parent::findOne($query, $fields); | ||
$this->log($log); | ||
$data = parent::findOne($query, $fields); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::getDBRef() | ||
*/ | ||
public function getDBRef(array $reference) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'getDBRef' => true, | ||
'reference' => $reference, | ||
)); | ||
); | ||
|
||
return parent::getDBRef($reference); | ||
$this->log($log); | ||
$data = parent::getDBRef($reference); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::group() | ||
*/ | ||
public function group($keys, array $initial, $reduce, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'group' => true, | ||
'keys' => $keys, | ||
'initial' => $initial, | ||
'reduce' => $reduce, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::group($keys, $initial, $reduce, $options); | ||
$this->log($log); | ||
$data = parent::group($keys, $initial, $reduce, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::insert() | ||
*/ | ||
public function insert(array &$a, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'insert' => true, | ||
'document' => $a, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::insert($a, $options); | ||
$this->log($log); | ||
$data = parent::insert($a, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::remove() | ||
*/ | ||
public function remove(array $query, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'remove' => true, | ||
'query' => $query, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::remove($query, $options); | ||
$this->log($log); | ||
$data = parent::remove($query, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::save() | ||
*/ | ||
public function save(array &$a, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'save' => true, | ||
'document' => $a, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::save($a, $options); | ||
$this->log($log); | ||
$data = parent::save($a, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::update() | ||
*/ | ||
public function update($query, array $newObj, array $options = array()) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'update' => true, | ||
'query' => $query, | ||
'newObj' => $newObj, | ||
'options' => $options, | ||
)); | ||
); | ||
|
||
return parent::update($query, $newObj, $options); | ||
$this->log($log); | ||
$data = parent::update($query, $newObj, $options); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
* @see Collection::validate() | ||
*/ | ||
public function validate($scanData = false) | ||
{ | ||
$this->log(array( | ||
$log = array( | ||
'validate' => true, | ||
'scanData' => $scanData, | ||
)); | ||
); | ||
|
||
return parent::validate($scanData); | ||
$this->log($log); | ||
$data = parent::validate($scanData); | ||
$this->logAfter(); | ||
return $data; | ||
} | ||
|
||
/** | ||
|
@@ -283,6 +348,6 @@ public function validate($scanData = false) | |
*/ | ||
protected function wrapCursor(\MongoCursor $cursor, $query, $fields) | ||
{ | ||
return new LoggableCursor($this, $cursor, $query, $fields, $this->numRetries, $this->loggerCallable); | ||
return new LoggableCursor($this, $cursor, $query, $fields, $this->numRetries, $this->loggerCallable, $this->queryLogger); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a
use
statement for the QueryLogger class? That makes it easier to see at a glance what the file is using.