summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/config.sample.php21
-rw-r--r--lib/private/log.php69
-rw-r--r--tests/lib/logger.php30
3 files changed, 113 insertions, 7 deletions
diff --git a/config/config.sample.php b/config/config.sample.php
index 45aaf6a107d..9a40f82252a 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -487,6 +487,27 @@ $CONFIG = array(
'loglevel' => 2,
/**
+ * Log condition for log level increase based on conditions. Once one of these
+ * conditions is met, the required log level is set to debug. This allows to
+ * debug specific requests, users or apps
+ *
+ * Supported conditions:
+ * - ``shared_secret``: if a request parameter with the name `log_secret` is set to
+ * this value the condition is met
+ * - ``users``: if the current request is done by one of the specified users,
+ * this condition is met
+ * - ``apps``: if the log message is invoked by one of the specified apps,
+ * this condition is met
+ *
+ * Defaults to an empty array.
+ */
+'log.condition' => [
+ 'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9',
+ 'users' => ['sample-user'],
+ 'apps' => ['files'],
+],
+
+/**
* This uses PHP.date formatting; see http://php.net/manual/en/function.date.php
*/
'logdateformat' => 'F d, Y H:i:s',
diff --git a/lib/private/log.php b/lib/private/log.php
index 2f15bec433f..840713b2eda 100644
--- a/lib/private/log.php
+++ b/lib/private/log.php
@@ -28,6 +28,7 @@
namespace OC;
use \OCP\ILogger;
+use OCP\Security\StringUtils;
/**
* logging utilities
@@ -41,15 +42,29 @@ use \OCP\ILogger;
class Log implements ILogger {
+ /** @var string */
private $logger;
+ /** @var SystemConfig */
+ private $config;
+
+ /** @var boolean|null cache the result of the log condition check for the request */
+ private $logConditionSatisfied = null;
/**
* @param string $logger The logger that should be used
+ * @param SystemConfig $config the system config object
*/
- public function __construct($logger=null) {
+ public function __construct($logger=null, SystemConfig $config=null) {
+ // FIXME: Add this for backwards compatibility, should be fixed at some point probably
+ if($config === null) {
+ $config = \OC::$server->getSystemConfig();
+ }
+
+ $this->config = $config;
+
// FIXME: Add this for backwards compatibility, should be fixed at some point probably
if($logger === null) {
- $this->logger = 'OC_Log_'.ucfirst(\OC_Config::getValue('log_type', 'owncloud'));
+ $this->logger = 'OC_Log_'.ucfirst($this->config->getValue('log_type', 'owncloud'));
call_user_func(array($this->logger, 'init'));
} else {
$this->logger = $logger;
@@ -158,8 +173,22 @@ class Log implements ILogger {
* @param array $context
*/
public function log($level, $message, array $context = array()) {
+ $minLevel = min($this->config->getValue('loglevel', \OC_Log::WARN), \OC_Log::ERROR);
+ $logCondition = $this->config->getValue('log.condition', []);
+
if (isset($context['app'])) {
$app = $context['app'];
+
+ /**
+ * check log condition based on the context of each log message
+ * once this is met -> change the required log level to debug
+ */
+ if(!empty($logCondition)
+ && isset($logCondition['apps'])
+ && in_array($app, $logCondition['apps'], true)) {
+ $minLevel = \OC_Log::DEBUG;
+ }
+
} else {
$app = 'no app in context';
}
@@ -172,9 +201,41 @@ class Log implements ILogger {
// interpolate replacement values into the message and return
$message = strtr($message, $replace);
- $config = \OC::$server->getSystemConfig();
+ /**
+ * check for a special log condition - this enables an increased log on
+ * a per request/user base
+ */
+ if($this->logConditionSatisfied === null) {
+ // default to false to just process this once per request
+ $this->logConditionSatisfied = false;
+ if(!empty($logCondition)) {
+
+ // check for secret token in the request
+ if(isset($logCondition['shared_secret'])) {
+ $request = \OC::$server->getRequest();
+
+ // if token is found in the request change set the log condition to satisfied
+ if($request && StringUtils::equals($request->getParam('log_secret'), $logCondition['shared_secret'])) {
+ $this->logConditionSatisfied = true;
+ }
+ }
+
+ // check for user
+ if(isset($logCondition['users'])) {
+ $user = \OC::$server->getUserSession()->getUser();
+
+ // if the user matches set the log condition to satisfied
+ if($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
+ $this->logConditionSatisfied = true;
+ }
+ }
+ }
+ }
- $minLevel = min($config->getValue('loglevel', \OC_Log::WARN), \OC_Log::ERROR);
+ // if log condition is satisfied change the required log level to DEBUG
+ if($this->logConditionSatisfied) {
+ $minLevel = \OC_Log::DEBUG;
+ }
if ($level >= $minLevel) {
$logger = $this->logger;
diff --git a/tests/lib/logger.php b/tests/lib/logger.php
index 700a847917b..9a9f5be12fc 100644
--- a/tests/lib/logger.php
+++ b/tests/lib/logger.php
@@ -21,14 +21,38 @@ class Logger extends TestCase {
parent::setUp();
self::$logs = array();
- $this->logger = new Log('Test\Logger');
+ $this->config = $this->getMockBuilder(
+ '\OC\SystemConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->logger = new Log('Test\Logger', $this->config);
}
public function testInterpolation() {
$logger = $this->logger;
- $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
+ $logger->warning('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
- $expected = array('1 {Message {nothing} Bob Bar a}');
+ $expected = array('2 {Message {nothing} Bob Bar a}');
+ $this->assertEquals($expected, $this->getLogs());
+ }
+
+ public function testAppCondition() {
+ $this->config->expects($this->any())
+ ->method('getValue')
+ ->will(($this->returnValueMap([
+ ['loglevel', \OC_Log::WARN, \OC_Log::WARN],
+ ['log.condition', [], ['apps' => ['files']]]
+ ])));
+ $logger = $this->logger;
+
+ $logger->info('Don\'t display info messages');
+ $logger->info('Show info messages of files app', ['app' => 'files']);
+ $logger->warning('Show warning messages of other apps');
+
+ $expected = [
+ '1 Show info messages of files app',
+ '2 Show warning messages of other apps',
+ ];
$this->assertEquals($expected, $this->getLogs());
}