Merge pull request #4515 from nextcloud/downstream-27643
Adjust query/event logging code in favour of more complex owncloud/di…
This commit is contained in:
commit
01705b1b6a
15 changed files with 242 additions and 141 deletions
|
@ -517,8 +517,6 @@ return array(
|
|||
'OC\\DateTimeZone' => $baseDir . '/lib/private/DateTimeZone.php',
|
||||
'OC\\Diagnostics\\Event' => $baseDir . '/lib/private/Diagnostics/Event.php',
|
||||
'OC\\Diagnostics\\EventLogger' => $baseDir . '/lib/private/Diagnostics/EventLogger.php',
|
||||
'OC\\Diagnostics\\NullEventLogger' => $baseDir . '/lib/private/Diagnostics/NullEventLogger.php',
|
||||
'OC\\Diagnostics\\NullQueryLogger' => $baseDir . '/lib/private/Diagnostics/NullQueryLogger.php',
|
||||
'OC\\Diagnostics\\Query' => $baseDir . '/lib/private/Diagnostics/Query.php',
|
||||
'OC\\Diagnostics\\QueryLogger' => $baseDir . '/lib/private/Diagnostics/QueryLogger.php',
|
||||
'OC\\Encryption\\DecryptAll' => $baseDir . '/lib/private/Encryption/DecryptAll.php',
|
||||
|
|
|
@ -547,8 +547,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\DateTimeZone' => __DIR__ . '/../../..' . '/lib/private/DateTimeZone.php',
|
||||
'OC\\Diagnostics\\Event' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/Event.php',
|
||||
'OC\\Diagnostics\\EventLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/EventLogger.php',
|
||||
'OC\\Diagnostics\\NullEventLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/NullEventLogger.php',
|
||||
'OC\\Diagnostics\\NullQueryLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/NullQueryLogger.php',
|
||||
'OC\\Diagnostics\\Query' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/Query.php',
|
||||
'OC\\Diagnostics\\QueryLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/QueryLogger.php',
|
||||
'OC\\Encryption\\DecryptAll' => __DIR__ . '/../../..' . '/lib/private/Encryption/DecryptAll.php',
|
||||
|
|
|
@ -167,9 +167,6 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
|
|||
$statement = $this->replaceTablePrefix($statement);
|
||||
$statement = $this->adapter->fixupStatement($statement);
|
||||
|
||||
if(\OC::$server->getSystemConfig()->getValue( 'log_query', false)) {
|
||||
\OCP\Util::writeLog('core', 'DB prepare : '.$statement, \OCP\Util::DEBUG);
|
||||
}
|
||||
return parent::prepare($statement);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
|
@ -29,28 +31,53 @@ class EventLogger implements IEventLogger {
|
|||
/**
|
||||
* @var \OC\Diagnostics\Event[]
|
||||
*/
|
||||
private $events = array();
|
||||
private $events = [];
|
||||
|
||||
/**
|
||||
* @var bool - Module needs to be activated by some app
|
||||
*/
|
||||
private $activated = false;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function start($id, $description) {
|
||||
$this->events[$id] = new Event($id, $description, microtime(true));
|
||||
if ($this->activated){
|
||||
$this->events[$id] = new Event($id, $description, microtime(true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function end($id) {
|
||||
if (isset($this->events[$id])) {
|
||||
if ($this->activated && isset($this->events[$id])) {
|
||||
$timing = $this->events[$id];
|
||||
$timing->end(microtime(true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function log($id, $description, $start, $end) {
|
||||
$this->events[$id] = new Event($id, $description, $start);
|
||||
$this->events[$id]->end($end);
|
||||
if ($this->activated) {
|
||||
$this->events[$id] = new Event($id, $description, $start);
|
||||
$this->events[$id]->end($end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCP\Diagnostics\IEvent[]
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getEvents() {
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function activate() {
|
||||
$this->activated = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Diagnostics;
|
||||
|
||||
use OCP\Diagnostics\IEventLogger;
|
||||
|
||||
/**
|
||||
* Dummy event logger that doesn't actually log anything
|
||||
*/
|
||||
class NullEventLogger implements IEventLogger {
|
||||
/**
|
||||
* Mark the start of an event
|
||||
*
|
||||
* @param $id
|
||||
* @param $description
|
||||
*/
|
||||
public function start($id, $description) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the end of an event
|
||||
*
|
||||
* @param $id
|
||||
*/
|
||||
public function end($id) {
|
||||
}
|
||||
|
||||
public function log($id, $description, $start, $end) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCP\Diagnostics\IEvent[]
|
||||
*/
|
||||
public function getEvents() {
|
||||
return array();
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Diagnostics;
|
||||
|
||||
use OCP\Diagnostics\IQueryLogger;
|
||||
|
||||
class NullQueryLogger implements IQueryLogger {
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $params
|
||||
* @param array $types
|
||||
*/
|
||||
public function startQuery($sql, array $params = null, array $types = null) {
|
||||
}
|
||||
|
||||
public function stopQuery() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCP\Diagnostics\IQuery[]
|
||||
*/
|
||||
public function getQueries() {
|
||||
return array();
|
||||
}
|
||||
}
|
|
@ -67,7 +67,14 @@ class Query implements IQuery {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @return float
|
||||
*/
|
||||
public function getStart() {
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getDuration() {
|
||||
return $this->end - $this->start;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
|
@ -46,12 +48,17 @@ class QueryLogger implements IQueryLogger {
|
|||
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $params
|
||||
* @param array $types
|
||||
* @var bool - Module needs to be activated by some app
|
||||
*/
|
||||
private $activated = false;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function startQuery($sql, array $params = null, array $types = null) {
|
||||
$this->activeQuery = new Query($sql, $params, microtime(true), $this->getStack());
|
||||
if ($this->activated) {
|
||||
$this->activeQuery = new Query($sql, $params, microtime(true), $this->getStack());
|
||||
}
|
||||
}
|
||||
|
||||
private function getStack() {
|
||||
|
@ -62,8 +69,11 @@ class QueryLogger implements IQueryLogger {
|
|||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function stopQuery() {
|
||||
if ($this->activeQuery) {
|
||||
if ($this->activated && $this->activeQuery) {
|
||||
$this->activeQuery->end(microtime(true));
|
||||
$this->queries[] = $this->activeQuery;
|
||||
$this->activeQuery = null;
|
||||
|
@ -71,9 +81,16 @@ class QueryLogger implements IQueryLogger {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Query[]
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getQueries() {
|
||||
return $this->queries->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function activate() {
|
||||
$this->activated = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -603,22 +603,23 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
);
|
||||
});
|
||||
$this->registerAlias('HttpClientService', \OCP\Http\Client\IClientService::class);
|
||||
|
||||
$this->registerService(\OCP\Diagnostics\IEventLogger::class, function (Server $c) {
|
||||
$eventLogger = new EventLogger();
|
||||
if ($c->getSystemConfig()->getValue('debug', false)) {
|
||||
return new EventLogger();
|
||||
} else {
|
||||
return new NullEventLogger();
|
||||
// In debug mode, module is being activated by default
|
||||
$eventLogger->activate();
|
||||
}
|
||||
return $eventLogger;
|
||||
});
|
||||
$this->registerAlias('EventLogger', \OCP\Diagnostics\IEventLogger::class);
|
||||
|
||||
$this->registerService(\OCP\Diagnostics\IQueryLogger::class, function (Server $c) {
|
||||
$queryLogger = new QueryLogger();
|
||||
if ($c->getSystemConfig()->getValue('debug', false)) {
|
||||
return new QueryLogger();
|
||||
} else {
|
||||
return new NullQueryLogger();
|
||||
// In debug mode, module is being activated by default
|
||||
$queryLogger->activate();
|
||||
}
|
||||
return $queryLogger;
|
||||
});
|
||||
$this->registerAlias('QueryLogger', \OCP\Diagnostics\IQueryLogger::class);
|
||||
|
||||
|
|
|
@ -64,14 +64,7 @@ class OC_DB_StatementWrapper {
|
|||
* @param array $input
|
||||
* @return \OC_DB_StatementWrapper|int
|
||||
*/
|
||||
public function execute($input=array()) {
|
||||
if(\OC::$server->getSystemConfig()->getValue( "log_query", false)) {
|
||||
$backTrace = debug_backtrace();
|
||||
$class = $backTrace[1]['class'] . ':' . $backTrace[1]['function'];
|
||||
$file = substr($backTrace[0]['file'], strlen(\OC::$SERVERROOT)) . ':' . $backTrace[0]['line'];
|
||||
$params_str = str_replace("\n", " ", var_export($input, true));
|
||||
\OCP\Util::writeLog('core', "DB execute with arguments : $params_str in $class; $file", \OCP\Util::DEBUG);
|
||||
}
|
||||
public function execute($input= []) {
|
||||
$this->lastArguments = $input;
|
||||
if (count($input) > 0) {
|
||||
$result = $this->statement->execute($input);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
|
@ -31,7 +32,7 @@ namespace OCP\Diagnostics;
|
|||
*/
|
||||
interface IEventLogger {
|
||||
/**
|
||||
* Mark the start of an event
|
||||
* Mark the start of an event setting its ID $id and providing event description $description.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $description
|
||||
|
@ -40,7 +41,9 @@ interface IEventLogger {
|
|||
public function start($id, $description);
|
||||
|
||||
/**
|
||||
* Mark the end of an event
|
||||
* Mark the end of an event with specific ID $id, marked by start() method.
|
||||
* Ending event should store \OCP\Diagnostics\IEvent to
|
||||
* be returned with getEvents() method.
|
||||
*
|
||||
* @param string $id
|
||||
* @since 8.0.0
|
||||
|
@ -48,6 +51,11 @@ interface IEventLogger {
|
|||
public function end($id);
|
||||
|
||||
/**
|
||||
* Mark the start and the end of an event with specific ID $id and description $description,
|
||||
* explicitly marking start and end of the event, represented by $start and $end timestamps.
|
||||
* Logging event should store \OCP\Diagnostics\IEvent to
|
||||
* be returned with getEvents() method.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $description
|
||||
* @param float $start
|
||||
|
@ -57,8 +65,21 @@ interface IEventLogger {
|
|||
public function log($id, $description, $start, $end);
|
||||
|
||||
/**
|
||||
* This method should return all \OCP\Diagnostics\IEvent objects stored using
|
||||
* start()/end() or log() methods
|
||||
*
|
||||
* @return \OCP\Diagnostics\IEvent[]
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function getEvents();
|
||||
|
||||
/**
|
||||
* Activate the module for the duration of the request. Deactivated module
|
||||
* does not create and store \OCP\Diagnostics\IEvent objects.
|
||||
* Only activated module should create and store objects to be
|
||||
* returned with getEvents() call.
|
||||
*
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function activate();
|
||||
}
|
||||
|
|
|
@ -59,4 +59,9 @@ interface IQuery {
|
|||
* @since 11.0.0
|
||||
*/
|
||||
public function getStacktrace();
|
||||
/**
|
||||
* @return array
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function getStart();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
|
@ -33,6 +34,10 @@ use Doctrine\DBAL\Logging\SQLLogger;
|
|||
*/
|
||||
interface IQueryLogger extends SQLLogger {
|
||||
/**
|
||||
* Mark the start of a query providing query SQL statement, its parameters and types.
|
||||
* This method should be called as close to the DB as possible and after
|
||||
* query is finished finalized with stopQuery() method.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $params
|
||||
* @param array $types
|
||||
|
@ -41,14 +46,30 @@ interface IQueryLogger extends SQLLogger {
|
|||
public function startQuery($sql, array $params = null, array $types = null);
|
||||
|
||||
/**
|
||||
* Mark the end of the current active query. Ending query should store \OCP\Diagnostics\IQuery to
|
||||
* be returned with getQueries() method.
|
||||
*
|
||||
* @return mixed
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function stopQuery();
|
||||
|
||||
/**
|
||||
* This method should return all \OCP\Diagnostics\IQuery objects stored using
|
||||
* startQuery()/stopQuery() methods.
|
||||
*
|
||||
* @return \OCP\Diagnostics\IQuery[]
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function getQueries();
|
||||
|
||||
/**
|
||||
* Activate the module for the duration of the request. Deactivated module
|
||||
* does not create and store \OCP\Diagnostics\IQuery objects.
|
||||
* Only activated module should create and store objects to be
|
||||
* returned with getQueries() call.
|
||||
*
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function activate();
|
||||
}
|
||||
|
|
66
tests/lib/Diagnostics/EventLoggerTest.php
Normal file
66
tests/lib/Diagnostics/EventLoggerTest.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2017, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\Diagnostics;
|
||||
|
||||
use OC\Diagnostics\EventLogger;
|
||||
use Test\TestCase;
|
||||
|
||||
class EventLoggerTest extends TestCase {
|
||||
|
||||
/** @var \OC\Diagnostics\EventLogger */
|
||||
private $logger;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = new EventLogger();
|
||||
}
|
||||
|
||||
public function testQueryLogger() {
|
||||
// Module is not activated and this should not be logged
|
||||
$this->logger->start("test1", "testevent1");
|
||||
$this->logger->end("test1");
|
||||
$this->logger->log("test2", "testevent2", microtime(true), microtime(true));
|
||||
$events = $this->logger->getEvents();
|
||||
$this->assertSame(0, sizeof($events));
|
||||
|
||||
// Activate module and log some query
|
||||
$this->logger->activate();
|
||||
|
||||
// start one event
|
||||
$this->logger->start("test3", "testevent3");
|
||||
|
||||
// force log of another event
|
||||
$this->logger->log("test4", "testevent4", microtime(true), microtime(true));
|
||||
|
||||
// log started event
|
||||
$this->logger->end("test3");
|
||||
|
||||
$events = $this->logger->getEvents();
|
||||
$this->assertSame("test4", $events['test4']->getId());
|
||||
$this->assertSame("testevent4", $events['test4']->getDescription());
|
||||
$this->assertSame("test3", $events['test3']->getId());
|
||||
$this->assertSame("testevent3", $events['test3']->getDescription());
|
||||
$this->assertSame(2, sizeof($events));
|
||||
|
||||
}
|
||||
}
|
54
tests/lib/Diagnostics/QueryLoggerTest.php
Normal file
54
tests/lib/Diagnostics/QueryLoggerTest.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Piotr Mrowczynski <piotr@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2017, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Test\Diagnostics;
|
||||
|
||||
use OC\Diagnostics\QueryLogger;
|
||||
use Test\TestCase;
|
||||
|
||||
class QueryLoggerTest extends TestCase {
|
||||
|
||||
/** @var \OC\Diagnostics\QueryLogger */
|
||||
private $logger;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = new QueryLogger();
|
||||
}
|
||||
|
||||
public function testQueryLogger() {
|
||||
// Module is not activated and this should not be logged
|
||||
$this->logger->startQuery("SELECT", ["testuser", "count"], ["string", "int"]);
|
||||
$this->logger->stopQuery();
|
||||
$queries = $this->logger->getQueries();
|
||||
$this->assertSame(0, sizeof($queries));
|
||||
|
||||
// Activate module and log some query
|
||||
$this->logger->activate();
|
||||
$this->logger->startQuery("SELECT", ["testuser", "count"], ["string", "int"]);
|
||||
$this->logger->stopQuery();
|
||||
|
||||
$queries = $this->logger->getQueries();
|
||||
$this->assertSame(1, sizeof($queries));
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue