summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2018-05-02 16:16:28 +0200
committerGitHub <noreply@github.com>2018-05-02 16:16:28 +0200
commit2aa108000cd5bb29b7be5d7226185b5c1be59e29 (patch)
tree46d6e45c3e88bfa46bd868f6120896b2a52a2948
parenta56ec1062af36c02666277f7f97f6a407a87d1e1 (diff)
parentaff5fe68b31c3663be2a114666650d2f8723a22b (diff)
downloadnextcloud-server-2aa108000cd5bb29b7be5d7226185b5c1be59e29.tar.gz
nextcloud-server-2aa108000cd5bb29b7be5d7226185b5c1be59e29.zip
Merge pull request #9293 from nextcloud/feature/9166/custom-auditlogfile
option for a seperate audit log file
-rw-r--r--apps/admin_audit/appinfo/info.xml3
-rw-r--r--apps/admin_audit/composer/composer/autoload_classmap.php1
-rw-r--r--apps/admin_audit/composer/composer/autoload_static.php1
-rw-r--r--apps/admin_audit/lib/AppInfo/Application.php98
-rw-r--r--apps/admin_audit/lib/BackgroundJobs/Rotate.php52
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php2
-rw-r--r--lib/composer/composer/autoload_classmap.php5
-rw-r--r--lib/composer/composer/autoload_static.php5
-rw-r--r--lib/private/Log.php46
-rw-r--r--lib/private/Log/Errorlog.php11
-rw-r--r--lib/private/Log/File.php71
-rw-r--r--lib/private/Log/LogFactory.php78
-rw-r--r--lib/private/Log/Rotate.php26
-rw-r--r--lib/private/Log/Syslog.php25
-rw-r--r--lib/private/Server.php21
-rw-r--r--lib/public/IServerContainer.php9
-rw-r--r--lib/public/Log/IFileBased.php43
-rw-r--r--lib/public/Log/ILogFactory.php48
-rw-r--r--lib/public/Log/IWriter.php37
-rw-r--r--lib/public/Log/RotationTrait.php71
-rw-r--r--settings/Controller/LogSettingsController.php17
-rw-r--r--tests/lib/Log/FileTest.php29
-rw-r--r--tests/lib/Log/LogFactoryTest.php144
-rw-r--r--tests/lib/LoggerTest.php34
24 files changed, 683 insertions, 194 deletions
diff --git a/apps/admin_audit/appinfo/info.xml b/apps/admin_audit/appinfo/info.xml
index 054ed9580f2..3006551b409 100644
--- a/apps/admin_audit/appinfo/info.xml
+++ b/apps/admin_audit/appinfo/info.xml
@@ -17,4 +17,7 @@
<dependencies>
<nextcloud min-version="14" max-version="14" />
</dependencies>
+ <background-jobs>
+ <job>OCA\AdminAudit\BackgroundJobs\Rotate</job>
+ </background-jobs>
</info>
diff --git a/apps/admin_audit/composer/composer/autoload_classmap.php b/apps/admin_audit/composer/composer/autoload_classmap.php
index c08200c7c20..95ddaac7452 100644
--- a/apps/admin_audit/composer/composer/autoload_classmap.php
+++ b/apps/admin_audit/composer/composer/autoload_classmap.php
@@ -18,4 +18,5 @@ return array(
'OCA\\AdminAudit\\Actions\\UserManagement' => $baseDir . '/../lib/Actions/UserManagement.php',
'OCA\\AdminAudit\\Actions\\Versions' => $baseDir . '/../lib/Actions/Versions.php',
'OCA\\AdminAudit\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
+ 'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => $baseDir . '/../lib/BackgroundJobs/Rotate.php',
);
diff --git a/apps/admin_audit/composer/composer/autoload_static.php b/apps/admin_audit/composer/composer/autoload_static.php
index ef088bd22d9..1c01a35ceb2 100644
--- a/apps/admin_audit/composer/composer/autoload_static.php
+++ b/apps/admin_audit/composer/composer/autoload_static.php
@@ -33,6 +33,7 @@ class ComposerStaticInitAdminAudit
'OCA\\AdminAudit\\Actions\\UserManagement' => __DIR__ . '/..' . '/../lib/Actions/UserManagement.php',
'OCA\\AdminAudit\\Actions\\Versions' => __DIR__ . '/..' . '/../lib/Actions/Versions.php',
'OCA\\AdminAudit\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
+ 'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => __DIR__ . '/..' . '/../lib/BackgroundJobs/Rotate.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/apps/admin_audit/lib/AppInfo/Application.php b/apps/admin_audit/lib/AppInfo/Application.php
index df39e3eb111..77b76885a20 100644
--- a/apps/admin_audit/lib/AppInfo/Application.php
+++ b/apps/admin_audit/lib/AppInfo/Application.php
@@ -53,8 +53,26 @@ use OCP\Share;
class Application extends App {
+ /** @var ILogger */
+ protected $logger;
+
public function __construct() {
parent::__construct('admin_audit');
+ $this->initLogger();
+ }
+
+ public function initLogger() {
+ $c = $this->getContainer()->getServer();
+ $config = $c->getConfig();
+
+ $default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log';
+ $logFile = $config->getAppValue('admin_audit', 'logfile', $default);
+ if($logFile === null) {
+ $this->logger = $c->getLogger();
+ return;
+ }
+ $this->logger = $c->getLogFactory()->getCustomLogger($logFile);
+
}
public function register() {
@@ -65,26 +83,24 @@ class Application extends App {
* Register hooks in order to log them
*/
protected function registerHooks() {
- $logger = $this->getContainer()->getServer()->getLogger();
-
- $this->userManagementHooks($logger);
- $this->groupHooks($logger);
- $this->authHooks($logger);
+ $this->userManagementHooks();
+ $this->groupHooks();
+ $this->authHooks();
- $this->consoleHooks($logger);
- $this->appHooks($logger);
+ $this->consoleHooks();
+ $this->appHooks();
- $this->sharingHooks($logger);
+ $this->sharingHooks();
- $this->fileHooks($logger);
- $this->trashbinHooks($logger);
- $this->versionsHooks($logger);
+ $this->fileHooks();
+ $this->trashbinHooks();
+ $this->versionsHooks();
- $this->securityHooks($logger);
+ $this->securityHooks();
}
- protected function userManagementHooks(ILogger $logger) {
- $userActions = new UserManagement($logger);
+ protected function userManagementHooks() {
+ $userActions = new UserManagement($this->logger);
Util::connectHook('OC_User', 'post_createUser', $userActions, 'create');
Util::connectHook('OC_User', 'post_deleteUser', $userActions, 'delete');
@@ -97,8 +113,8 @@ class Application extends App {
$userSession->listen('\OC\User', 'postUnassignedUserId', [$userActions, 'unassign']);
}
- protected function groupHooks(ILogger $logger) {
- $groupActions = new GroupManagement($logger);
+ protected function groupHooks() {
+ $groupActions = new GroupManagement($this->logger);
/** @var IGroupManager|Manager $groupManager */
$groupManager = $this->getContainer()->getServer()->getGroupManager();
@@ -108,8 +124,8 @@ class Application extends App {
$groupManager->listen('\OC\Group', 'postCreate', [$groupActions, 'createGroup']);
}
- protected function sharingHooks(ILogger $logger) {
- $shareActions = new Sharing($logger);
+ protected function sharingHooks() {
+ $shareActions = new Sharing($this->logger);
Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared');
Util::connectHook(Share::class, 'post_unshare', $shareActions, 'unshare');
@@ -119,42 +135,42 @@ class Application extends App {
Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed');
}
- protected function authHooks(ILogger $logger) {
- $authActions = new Auth($logger);
+ protected function authHooks() {
+ $authActions = new Auth($this->logger);
Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt');
Util::connectHook('OC_User', 'post_login', $authActions, 'loginSuccessful');
Util::connectHook('OC_User', 'logout', $authActions, 'logout');
}
- protected function appHooks(ILogger $logger) {
+ protected function appHooks() {
$eventDispatcher = $this->getContainer()->getServer()->getEventDispatcher();
- $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function(ManagerEvent $event) use ($logger) {
- $appActions = new AppManagement($logger);
+ $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function(ManagerEvent $event) {
+ $appActions = new AppManagement($this->logger);
$appActions->enableApp($event->getAppID());
});
- $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, function(ManagerEvent $event) use ($logger) {
- $appActions = new AppManagement($logger);
+ $eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, function(ManagerEvent $event) {
+ $appActions = new AppManagement($this->logger);
$appActions->enableAppForGroups($event->getAppID(), $event->getGroups());
});
- $eventDispatcher->addListener(ManagerEvent::EVENT_APP_DISABLE, function(ManagerEvent $event) use ($logger) {
- $appActions = new AppManagement($logger);
+ $eventDispatcher->addListener(ManagerEvent::EVENT_APP_DISABLE, function(ManagerEvent $event) {
+ $appActions = new AppManagement($this->logger);
$appActions->disableApp($event->getAppID());
});
}
- protected function consoleHooks(ILogger $logger) {
+ protected function consoleHooks() {
$eventDispatcher = $this->getContainer()->getServer()->getEventDispatcher();
- $eventDispatcher->addListener(ConsoleEvent::EVENT_RUN, function(ConsoleEvent $event) use ($logger) {
- $appActions = new Console($logger);
+ $eventDispatcher->addListener(ConsoleEvent::EVENT_RUN, function(ConsoleEvent $event) {
+ $appActions = new Console($this->logger);
$appActions->runCommand($event->getArguments());
});
}
- protected function fileHooks(ILogger $logger) {
- $fileActions = new Files($logger);
+ protected function fileHooks() {
+ $fileActions = new Files($this->logger);
$eventDispatcher = $this->getContainer()->getServer()->getEventDispatcher();
$eventDispatcher->addListener(
IPreview::EVENT,
@@ -215,26 +231,26 @@ class Application extends App {
);
}
- protected function versionsHooks(ILogger $logger) {
- $versionsActions = new Versions($logger);
+ protected function versionsHooks() {
+ $versionsActions = new Versions($this->logger);
Util::connectHook('\OCP\Versions', 'rollback', $versionsActions, 'rollback');
Util::connectHook('\OCP\Versions', 'delete',$versionsActions, 'delete');
}
- protected function trashbinHooks(ILogger $logger) {
- $trashActions = new Trashbin($logger);
+ protected function trashbinHooks() {
+ $trashActions = new Trashbin($this->logger);
Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete');
Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore');
}
- protected function securityHooks(ILogger $logger) {
+ protected function securityHooks() {
$eventDispatcher = $this->getContainer()->getServer()->getEventDispatcher();
- $eventDispatcher->addListener(IProvider::EVENT_SUCCESS, function(GenericEvent $event) use ($logger) {
- $security = new Security($logger);
+ $eventDispatcher->addListener(IProvider::EVENT_SUCCESS, function(GenericEvent $event) {
+ $security = new Security($this->logger);
$security->twofactorSuccess($event->getSubject(), $event->getArguments());
});
- $eventDispatcher->addListener(IProvider::EVENT_FAILED, function(GenericEvent $event) use ($logger) {
- $security = new Security($logger);
+ $eventDispatcher->addListener(IProvider::EVENT_FAILED, function(GenericEvent $event) {
+ $security = new Security($this->logger);
$security->twofactorFailed($event->getSubject(), $event->getArguments());
});
}
diff --git a/apps/admin_audit/lib/BackgroundJobs/Rotate.php b/apps/admin_audit/lib/BackgroundJobs/Rotate.php
new file mode 100644
index 00000000000..421ee65d643
--- /dev/null
+++ b/apps/admin_audit/lib/BackgroundJobs/Rotate.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\AdminAudit\BackgroundJobs;
+
+use OC\BackgroundJob\TimedJob;
+use OCP\Log\RotationTrait;
+
+class Rotate extends TimedJob {
+ use RotationTrait;
+
+ public function __construct() {
+ $this->setInterval(60*60*3);
+ }
+
+ protected function run($argument) {
+ $config = \OC::$server->getConfig();
+ $default = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/audit.log';
+ $this->filePath = $config->getAppValue('admin_audit', 'logfile', $default);
+
+ if($this->filePath === '') {
+ // default log file, nothing to do
+ return;
+ }
+
+ $this->maxSize = $config->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
+
+ if($this->shouldRotateBySize()) {
+ $this->rotate();
+ }
+ }
+}
diff --git a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
index c1d48a7ce5d..1de9333207f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
@@ -69,7 +69,7 @@ class ExceptionLoggerPluginTest extends TestCase {
});
$this->server = new Server();
- $this->logger = new TestLogger(Log\File::class, $config);
+ $this->logger = new TestLogger(new Log\File(\OC::$SERVERROOT.'/data/nextcloud.log', '', $config), $config);
$this->plugin = new PluginToTest('unit-test', $this->logger);
$this->plugin->initialize($this->server);
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 19cb583cc93..6f8c4131546 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -239,6 +239,10 @@ return array(
'OCP\\Lock\\ILockingProvider' => $baseDir . '/lib/public/Lock/ILockingProvider.php',
'OCP\\Lock\\LockedException' => $baseDir . '/lib/public/Lock/LockedException.php',
'OCP\\Lockdown\\ILockdownManager' => $baseDir . '/lib/public/Lockdown/ILockdownManager.php',
+ 'OCP\\Log\\IFileBased' => $baseDir . '/lib/public/Log/IFileBased.php',
+ 'OCP\\Log\\ILogFactory' => $baseDir . '/lib/public/Log/ILogFactory.php',
+ 'OCP\\Log\\IWriter' => $baseDir . '/lib/public/Log/IWriter.php',
+ 'OCP\\Log\\RotationTrait' => $baseDir . '/lib/public/Log/RotationTrait.php',
'OCP\\Mail\\IAttachment' => $baseDir . '/lib/public/Mail/IAttachment.php',
'OCP\\Mail\\IEMailTemplate' => $baseDir . '/lib/public/Mail/IEMailTemplate.php',
'OCP\\Mail\\IMailer' => $baseDir . '/lib/public/Mail/IMailer.php',
@@ -750,6 +754,7 @@ return array(
'OC\\Log\\Errorlog' => $baseDir . '/lib/private/Log/Errorlog.php',
'OC\\Log\\ExceptionSerializer' => $baseDir . '/lib/private/Log/ExceptionSerializer.php',
'OC\\Log\\File' => $baseDir . '/lib/private/Log/File.php',
+ 'OC\\Log\\LogFactory' => $baseDir . '/lib/private/Log/LogFactory.php',
'OC\\Log\\Rotate' => $baseDir . '/lib/private/Log/Rotate.php',
'OC\\Log\\Syslog' => $baseDir . '/lib/private/Log/Syslog.php',
'OC\\Mail\\Attachment' => $baseDir . '/lib/private/Mail/Attachment.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index a913b0498b9..92726f7789d 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -269,6 +269,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Lock\\ILockingProvider' => __DIR__ . '/../../..' . '/lib/public/Lock/ILockingProvider.php',
'OCP\\Lock\\LockedException' => __DIR__ . '/../../..' . '/lib/public/Lock/LockedException.php',
'OCP\\Lockdown\\ILockdownManager' => __DIR__ . '/../../..' . '/lib/public/Lockdown/ILockdownManager.php',
+ 'OCP\\Log\\IFileBased' => __DIR__ . '/../../..' . '/lib/public/Log/IFileBased.php',
+ 'OCP\\Log\\ILogFactory' => __DIR__ . '/../../..' . '/lib/public/Log/ILogFactory.php',
+ 'OCP\\Log\\IWriter' => __DIR__ . '/../../..' . '/lib/public/Log/IWriter.php',
+ 'OCP\\Log\\RotationTrait' => __DIR__ . '/../../..' . '/lib/public/Log/RotationTrait.php',
'OCP\\Mail\\IAttachment' => __DIR__ . '/../../..' . '/lib/public/Mail/IAttachment.php',
'OCP\\Mail\\IEMailTemplate' => __DIR__ . '/../../..' . '/lib/public/Mail/IEMailTemplate.php',
'OCP\\Mail\\IMailer' => __DIR__ . '/../../..' . '/lib/public/Mail/IMailer.php',
@@ -780,6 +784,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Log\\Errorlog' => __DIR__ . '/../../..' . '/lib/private/Log/Errorlog.php',
'OC\\Log\\ExceptionSerializer' => __DIR__ . '/../../..' . '/lib/private/Log/ExceptionSerializer.php',
'OC\\Log\\File' => __DIR__ . '/../../..' . '/lib/private/Log/File.php',
+ 'OC\\Log\\LogFactory' => __DIR__ . '/../../..' . '/lib/private/Log/LogFactory.php',
'OC\\Log\\Rotate' => __DIR__ . '/../../..' . '/lib/private/Log/Rotate.php',
'OC\\Log\\Syslog' => __DIR__ . '/../../..' . '/lib/private/Log/Syslog.php',
'OC\\Mail\\Attachment' => __DIR__ . '/../../..' . '/lib/private/Mail/Attachment.php',
diff --git a/lib/private/Log.php b/lib/private/Log.php
index ffe8c665c6f..69705c49e87 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -38,7 +38,8 @@ namespace OC;
use InterfaSys\LogNormalizer\Normalizer;
use OC\Log\ExceptionSerializer;
-use OC\Log\File;
+use OCP\Log\IFileBased;
+use OCP\Log\IWriter;
use OCP\ILogger;
use OCP\Support\CrashReport\IRegistry;
use OCP\Util;
@@ -54,7 +55,7 @@ use OCP\Util;
*/
class Log implements ILogger {
- /** @var string */
+ /** @var IWriter */
private $logger;
/** @var SystemConfig */
@@ -70,27 +71,19 @@ class Log implements ILogger {
private $crashReporters;
/**
- * @param string $logger The logger that should be used
+ * @param IWriter $logger The logger that should be used
* @param SystemConfig $config the system config object
* @param Normalizer|null $normalizer
* @param IRegistry|null $registry
*/
- public function __construct($logger = null, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
+ public function __construct(IWriter $logger, SystemConfig $config = null, $normalizer = null, IRegistry $registry = 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) {
- $logType = $this->config->getValue('log_type', 'file');
- $this->logger = static::getLogClass($logType);
- call_user_func([$this->logger, 'init']);
- } else {
- $this->logger = $logger;
- }
+ $this->logger = $logger;
if ($normalizer === null) {
$this->normalizer = new Normalizer();
} else {
@@ -302,7 +295,7 @@ class Log implements ILogger {
array_walk($context, [$this->normalizer, 'format']);
if ($level >= $minLevel) {
- if ($this->logger !== File::class) {
+ if (!$this->logger instanceof IFileBased) {
$data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR);
}
$this->writeLog($app, $data, $level);
@@ -320,28 +313,13 @@ class Log implements ILogger {
* @param int $level
*/
protected function writeLog(string $app, $entry, int $level) {
- call_user_func([$this->logger, 'write'], $app, $entry, $level);
+ $this->logger->write($app, $entry, $level);
}
- /**
- * @param string $logType
- * @return string
- * @internal
- */
- public static function getLogClass(string $logType): string {
- switch (strtolower($logType)) {
- case 'errorlog':
- return \OC\Log\Errorlog::class;
- case 'syslog':
- return \OC\Log\Syslog::class;
- case 'file':
- return \OC\Log\File::class;
-
- // Backwards compatibility for old and fallback for unknown log types
- case 'owncloud':
- case 'nextcloud':
- default:
- return \OC\Log\File::class;
+ public function getLogPath():string {
+ if($this->logger instanceof IFileBased) {
+ return $this->logger->getLogFilePath();
}
+ throw new \RuntimeException('Log implementation has no path');
}
}
diff --git a/lib/private/Log/Errorlog.php b/lib/private/Log/Errorlog.php
index 37498c36aba..9dc8b2cc49c 100644
--- a/lib/private/Log/Errorlog.php
+++ b/lib/private/Log/Errorlog.php
@@ -25,14 +25,9 @@
namespace OC\Log;
-class Errorlog {
+use OCP\Log\IWriter;
-
- /**
- * Init class data
- */
- public static function init() {
- }
+class Errorlog implements IWriter {
/**
* write a message in the log
@@ -40,7 +35,7 @@ class Errorlog {
* @param string $message
* @param int $level
*/
- public static function write($app, $message, $level) {
+ public function write(string $app, $message, int $level) {
error_log('[owncloud]['.$app.']['.$level.'] '.$message);
}
}
diff --git a/lib/private/Log/File.php b/lib/private/Log/File.php
index 755c4729c7a..597cb54e402 100644
--- a/lib/private/Log/File.php
+++ b/lib/private/Log/File.php
@@ -36,7 +36,9 @@
*/
namespace OC\Log;
-
+use OC\SystemConfig;
+use OCP\Log\IFileBased;
+use OCP\Log\IWriter;
use OCP\ILogger;
/**
@@ -45,30 +47,26 @@ use OCP\ILogger;
* Log is saved at data/nextcloud.log (on default)
*/
-class File {
- static protected $logFile;
-
- /**
- * Init class data
- */
- public static function init() {
- $systemConfig = \OC::$server->getSystemConfig();
- $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/nextcloud.log';
- self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile);
+class File implements IWriter, IFileBased {
+ /** @var string */
+ protected $logFile;
+ /** @var SystemConfig */
+ private $config;
- /**
- * Fall back to default log file if specified logfile does not exist
- * and can not be created.
- */
- if (!file_exists(self::$logFile)) {
- if(!is_writable(dirname(self::$logFile))) {
- self::$logFile = $defaultLogFile;
- } else {
- if(!touch(self::$logFile)) {
- self::$logFile = $defaultLogFile;
- }
+ public function __construct(string $path, string $fallbackPath = '', SystemConfig $config) {
+ $this->logFile = $path;
+ if (!file_exists($this->logFile)) {
+ if(
+ (
+ !is_writable(dirname($this->logFile))
+ || !touch($this->logFile)
+ )
+ && $fallbackPath !== ''
+ ) {
+ $this->logFile = $fallbackPath;
}
}
+ $this->config = $config;
}
/**
@@ -77,12 +75,10 @@ class File {
* @param string|array $message
* @param int $level
*/
- public static function write($app, $message, $level) {
- $config = \OC::$server->getSystemConfig();
-
+ public function write(string $app, $message, int $level) {
// default to ISO8601
- $format = $config->getValue('logdateformat', \DateTime::ATOM);
- $logTimeZone = $config->getValue('logtimezone', 'UTC');
+ $format = $this->config->getValue('logdateformat', \DateTime::ATOM);
+ $logTimeZone = $this->config->getValue('logtimezone', 'UTC');
try {
$timezone = new \DateTimeZone($logTimeZone);
} catch (\Exception $e) {
@@ -102,7 +98,7 @@ class File {
$time = $time->format($format);
$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
- if($config->getValue('installed', false)) {
+ if($this->config->getValue('installed', false)) {
$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
} else {
$user = '--';
@@ -111,7 +107,7 @@ class File {
if ($userAgent === '') {
$userAgent = '--';
}
- $version = $config->getValue('version', '');
+ $version = $this->config->getValue('version', '');
$entry = compact(
'reqId',
'level',
@@ -137,9 +133,9 @@ class File {
}
}
$entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
- $handle = @fopen(self::$logFile, 'a');
- if ((fileperms(self::$logFile) & 0777) != 0640) {
- @chmod(self::$logFile, 0640);
+ $handle = @fopen($this->logFile, 'a');
+ if ((fileperms($this->logFile) & 0777) != 0640) {
+ @chmod($this->logFile, 0640);
}
if ($handle) {
fwrite($handle, $entry."\n");
@@ -159,11 +155,10 @@ class File {
* @param int $offset
* @return array
*/
- public static function getEntries($limit=50, $offset=0) {
- self::init();
- $minLevel = \OC::$server->getSystemConfig()->getValue("loglevel", ILogger::WARN);
+ public function getEntries(int $limit=50, int $offset=0):array {
+ $minLevel = $this->config->getValue("loglevel", ILogger::WARN);
$entries = array();
- $handle = @fopen(self::$logFile, 'rb');
+ $handle = @fopen($this->logFile, 'rb');
if ($handle) {
fseek($handle, 0, SEEK_END);
$pos = ftell($handle);
@@ -205,7 +200,7 @@ class File {
/**
* @return string
*/
- public static function getLogFilePath() {
- return self::$logFile;
+ public function getLogFilePath():string {
+ return $this->logFile;
}
}
diff --git a/lib/private/Log/LogFactory.php b/lib/private/Log/LogFactory.php
new file mode 100644
index 00000000000..9b9d12abfa8
--- /dev/null
+++ b/lib/private/Log/LogFactory.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Log;
+
+use OC\Log;
+use OC\SystemConfig;
+use OCP\ILogger;
+use OCP\IServerContainer;
+use OCP\Log\ILogFactory;
+use OCP\Log\IWriter;
+
+class LogFactory implements ILogFactory {
+ /** @var IServerContainer */
+ private $c;
+ /** @var SystemConfig */
+ private $systemConfig;
+
+ public function __construct(IServerContainer $c, SystemConfig $systemConfig) {
+ $this->c = $c;
+ $this->systemConfig = $systemConfig;
+ }
+
+ /**
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function get(string $type):IWriter {
+ switch (strtolower($type)) {
+ case 'errorlog':
+ return new Errorlog();
+ case 'syslog':
+ return $this->c->resolve(Syslog::class);
+ case 'file':
+ return $this->buildLogFile();
+
+ // Backwards compatibility for old and fallback for unknown log types
+ case 'owncloud':
+ case 'nextcloud':
+ default:
+ return $this->buildLogFile();
+ }
+ }
+
+ public function getCustomLogger(string $path):ILogger {
+ $log = $this->buildLogFile($path);
+ return new Log($log, $this->systemConfig);
+ }
+
+ protected function buildLogFile(string $logFile = ''):File {
+ $defaultLogFile = $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT.'/data').'/nextcloud.log';
+ if($logFile === '') {
+ $logFile = $this->systemConfig->getValue('logfile', $defaultLogFile);
+ }
+ $fallback = $defaultLogFile !== $logFile ? $defaultLogFile : '';
+
+ return new File($logFile, $fallback, $this->systemConfig);
+ }
+}
diff --git a/lib/private/Log/Rotate.php b/lib/private/Log/Rotate.php
index 48b96c98a8d..cc41c804ad3 100644
--- a/lib/private/Log/Rotate.php
+++ b/lib/private/Log/Rotate.php
@@ -24,7 +24,7 @@
*/
namespace OC\Log;
-use OCP\ILogger;
+use OCP\Log\RotationTrait;
/**
* This rotates the current logfile to a new name, this way the total log usage
@@ -33,23 +33,17 @@ use OCP\ILogger;
* location and manage that with your own tools.
*/
class Rotate extends \OC\BackgroundJob\Job {
- private $max_log_size;
+ use RotationTrait;
+
public function run($dummy) {
$systemConfig = \OC::$server->getSystemConfig();
- $logFile = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
- $this->max_log_size = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
- if ($this->max_log_size) {
- $filesize = @filesize($logFile);
- if ($filesize >= $this->max_log_size) {
- $this->rotate($logFile);
- }
- }
- }
+ $this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
- protected function rotate($logfile) {
- $rotatedLogfile = $logfile.'.1';
- rename($logfile, $rotatedLogfile);
- $msg = 'Log file "'.$logfile.'" was over '.$this->max_log_size.' bytes, moved to "'.$rotatedLogfile.'"';
- \OCP\Util::writeLog(Rotate::class, $msg, ILogger::WARN);
+ $this->maxSize = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
+ if($this->shouldRotateBySize()) {
+ $rotatedFile = $this->rotate();
+ $msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
+ \OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
+ }
}
}
diff --git a/lib/private/Log/Syslog.php b/lib/private/Log/Syslog.php
index 7b3d931ef31..90a20026f0e 100644
--- a/lib/private/Log/Syslog.php
+++ b/lib/private/Log/Syslog.php
@@ -26,23 +26,24 @@
namespace OC\Log;
use OCP\ILogger;
+use OCP\IConfig;
+use OCP\Log\IWriter;
-class Syslog {
- static protected $levels = array(
+class Syslog implements IWriter {
+ protected $levels = [
ILogger::DEBUG => LOG_DEBUG,
ILogger::INFO => LOG_INFO,
ILogger::WARN => LOG_WARNING,
ILogger::ERROR => LOG_ERR,
ILogger::FATAL => LOG_CRIT,
- );
+ ];
- /**
- * Init class data
- */
- public static function init() {
- openlog(\OC::$server->getSystemConfig()->getValue("syslog_tag", "ownCloud"), LOG_PID | LOG_CONS, LOG_USER);
- // Close at shutdown
- register_shutdown_function('closelog');
+ public function __construct(IConfig $config) {
+ openlog($config->getSystemValue('syslog_tag', 'ownCloud'), LOG_PID | LOG_CONS, LOG_USER);
+ }
+
+ public function __destruct() {
+ closelog();
}
/**
@@ -51,8 +52,8 @@ class Syslog {
* @param string $message
* @param int $level
*/
- public static function write($app, $message, $level) {
- $syslog_level = self::$levels[$level];
+ public function write(string $app, $message, int $level) {
+ $syslog_level = $this->levels[$level];
syslog($syslog_level, '{'.$app.'} '.$message);
}
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 3786486c2b2..a879c65bb9b 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -87,6 +87,7 @@ use OC\Lock\DBLockingProvider;
use OC\Lock\MemcacheLockingProvider;
use OC\Lock\NoopLockingProvider;
use OC\Lockdown\LockdownManager;
+use OC\Log\LogFactory;
use OC\Mail\Mailer;
use OC\Memcache\ArrayCache;
use OC\Memcache\Factory;
@@ -134,6 +135,7 @@ use OCP\ITempManager;
use OCP\Contacts\ContactsMenu\IActionFactory;
use OCP\IUser;
use OCP\Lock\ILockingProvider;
+use OCP\Log\ILogFactory;
use OCP\Remote\Api\IApiFactory;
use OCP\Remote\IInstanceFactory;
use OCP\RichObjectStrings\IValidator;
@@ -546,15 +548,18 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(\OCP\ILogger::class, function (Server $c) {
$logType = $c->query('AllConfig')->getSystemValue('log_type', 'file');
- $logger = Log::getLogClass($logType);
- call_user_func(array($logger, 'init'));
- $config = $this->getSystemConfig();
+ $factory = new LogFactory($c, $this->getSystemConfig());
+ $logger = $factory->get($logType);
$registry = $c->query(\OCP\Support\CrashReport\IRegistry::class);
- return new Log($logger, $config, null, $registry);
+ return new Log($logger, $this->getSystemConfig(), null, $registry);
});
$this->registerAlias('Logger', \OCP\ILogger::class);
+ $this->registerService(ILogFactory::class, function (Server $c) {
+ return new LogFactory($c, $this->getSystemConfig());
+ });
+
$this->registerService(\OCP\BackgroundJob\IJobList::class, function (Server $c) {
$config = $c->getConfig();
return new \OC\BackgroundJob\JobList(
@@ -1529,6 +1534,14 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return ILogFactory
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function getLogFactory() {
+ return $this->query(ILogFactory::class);
+ }
+
+ /**
* Returns a router for generating and matching urls
*
* @return \OCP\Route\IRouter
diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php
index 19c9578ee23..c38aaf9f2cb 100644
--- a/lib/public/IServerContainer.php
+++ b/lib/public/IServerContainer.php
@@ -44,6 +44,7 @@
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
+use OCP\Log\ILogFactory;
use OCP\Security\IContentSecurityPolicyManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -315,6 +316,14 @@ interface IServerContainer extends IContainer {
public function getLogger();
/**
+ * returns a log factory instance
+ *
+ * @return ILogFactory
+ * @since 14.0.0
+ */
+ public function getLogFactory();
+
+ /**
* Returns a router for generating and matching urls
*
* @return \OCP\Route\IRouter
diff --git a/lib/public/Log/IFileBased.php b/lib/public/Log/IFileBased.php
new file mode 100644
index 00000000000..c0eef472975
--- /dev/null
+++ b/lib/public/Log/IFileBased.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Log;
+
+/**
+ * Interface IFileBased
+ *
+ * @package OCP\Log
+ *
+ * @since 14.0.0
+ */
+interface IFileBased {
+ /**
+ * @since 14.0.0
+ */
+ public function getLogFilePath():string;
+
+ /**
+ * @since 14.0.0
+ */
+ public function getEntries(int $limit=50, int $offset=0): array;
+}
diff --git a/lib/public/Log/ILogFactory.php b/lib/public/Log/ILogFactory.php
new file mode 100644
index 00000000000..d8e1ab4ee76
--- /dev/null
+++ b/lib/public/Log/ILogFactory.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Log;
+
+use OCP\ILogger;
+
+/**
+ * Interface ILogFactory
+ *
+ * @package OCP\Log
+ * @since 14.0.0
+ */
+interface ILogFactory {
+ /**
+ * @param string $type - one of: file, errorlog, syslog
+ * @return IWriter
+ * @since 14.0.0
+ */
+ public function get(string $type): IWriter;
+
+ /**
+ * @param string $path
+ * @return ILogger
+ * @since 14.0.0
+ */
+ public function getCustomLogger(string $path): ILogger;
+}
diff --git a/lib/public/Log/IWriter.php b/lib/public/Log/IWriter.php
new file mode 100644
index 00000000000..c9b906bf4a3
--- /dev/null
+++ b/lib/public/Log/IWriter.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Log;
+
+/**
+ * Interface IWriter
+ *
+ * @package OCP\Log
+ * @since 14.0.0
+ */
+interface IWriter {
+ /**
+ * @since 14.0.0
+ */
+ public function write(string $app, $message, int $level);
+}
diff --git a/lib/public/Log/RotationTrait.php b/lib/public/Log/RotationTrait.php
new file mode 100644
index 00000000000..df42bfeff1f
--- /dev/null
+++ b/lib/public/Log/RotationTrait.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Log;
+
+/**
+ * Trait RotationTrait
+ *
+ * @package OCP\Log
+ *
+ * @since 14.0.0
+ */
+trait RotationTrait {
+
+ /**
+ * @var string
+ * @since 14.0.0
+ */
+ protected $filePath;
+
+ /**
+ * @var int
+ * @since 14.0.0
+ */
+ protected $maxSize;
+
+ /**
+ * @return string the resulting new filepath
+ * @since 14.0.0
+ */
+ protected function rotate():string {
+ $rotatedFile = $this->filePath.'.1';
+ rename($this->filePath, $rotatedFile);
+ return $rotatedFile;
+ }
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ protected function shouldRotateBySize():bool {
+ if ((int)$this->maxSize > 0) {
+ $filesize = @filesize($this->filePath);
+ if ($filesize >= (int)$this->maxSize) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/settings/Controller/LogSettingsController.php b/settings/Controller/LogSettingsController.php
index 6405ff9ec73..ef195edce63 100644
--- a/settings/Controller/LogSettingsController.php
+++ b/settings/Controller/LogSettingsController.php
@@ -26,8 +26,11 @@
namespace OC\Settings\Controller;
+use OC\Log;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\StreamResponse;
+use OCP\ILogger;
+use OCP\IRequest;
/**
* Class LogSettingsController
@@ -35,6 +38,15 @@ use OCP\AppFramework\Http\StreamResponse;
* @package OC\Settings\Controller
*/
class LogSettingsController extends Controller {
+
+ /** @var ILogger */
+ private $log;
+
+ public function __construct(string $appName, IRequest $request, ILogger $logger) {
+ parent::__construct($appName, $request);
+ $this->log = $logger;
+ }
+
/**
* download logfile
*
@@ -43,7 +55,10 @@ class LogSettingsController extends Controller {
* @return StreamResponse
*/
public function download() {
- $resp = new StreamResponse(\OC\Log\File::getLogFilePath());
+ if(!$this->log instanceof Log) {
+ throw new \UnexpectedValueException('Log file not available');
+ }
+ $resp = new StreamResponse($this->log->getLogPath());
$resp->addHeader('Content-Type', 'application/octet-stream');
$resp->addHeader('Content-Disposition', 'attachment; filename="nextcloud.log"');
return $resp;
diff --git a/tests/lib/Log/FileTest.php b/tests/lib/Log/FileTest.php
index 53b5c62e81a..d5e550a7e8d 100644
--- a/tests/lib/Log/FileTest.php
+++ b/tests/lib/Log/FileTest.php
@@ -31,28 +31,31 @@ class FileTest extends TestCase
private $restore_logfile;
private $restore_logdateformat;
+ /** @var File */
+ protected $logFile;
+
protected function setUp() {
parent::setUp();
- $config = \OC::$server->getConfig();
- $this->restore_logfile = $config->getSystemValue("logfile");
- $this->restore_logdateformat = $config->getSystemValue('logdateformat');
+ $config = \OC::$server->getSystemConfig();
+ $this->restore_logfile = $config->getValue("logfile");
+ $this->restore_logdateformat = $config->getValue('logdateformat');
- $config->setSystemValue("logfile", $config->getSystemValue('datadirectory') . "/logtest");
- File::init();
+ $config->setValue("logfile", $config->getValue('datadirectory') . "/logtest.log");
+ $this->logFile = new File($config->getValue('datadirectory') . '/logtest.log', '', $config);
}
protected function tearDown() {
- $config = \OC::$server->getConfig();
+ $config = \OC::$server->getSystemConfig();
if (isset($this->restore_logfile)) {
- $config->getSystemValue("logfile", $this->restore_logfile);
+ $config->getValue("logfile", $this->restore_logfile);
} else {
- $config->deleteSystemValue("logfile");
+ $config->deleteValue("logfile");
}
if (isset($this->restore_logdateformat)) {
- $config->getSystemValue("logdateformat", $this->restore_logdateformat);
+ $config->getValue("logdateformat", $this->restore_logdateformat);
} else {
- $config->deleteSystemValue("logdateformat");
- }
- File::init();
+ $config->deleteValue("logdateformat");
+ }
+ $this->logFile = new File($this->restore_logfile, '', $config);
parent::tearDown();
}
@@ -63,7 +66,7 @@ class FileTest extends TestCase
# set format & write log line
$config->setSystemValue('logdateformat', 'u');
- File::write('test', 'message', ILogger::ERROR);
+ $this->logFile->write('test', 'message', ILogger::ERROR);
# read log line
$handle = @fopen($config->getSystemValue('logfile'), 'r');
diff --git a/tests/lib/Log/LogFactoryTest.php b/tests/lib/Log/LogFactoryTest.php
new file mode 100644
index 00000000000..08139f54df4
--- /dev/null
+++ b/tests/lib/Log/LogFactoryTest.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Log;
+use OC\Log\Errorlog;
+use OC\Log\File;
+use OC\Log\LogFactory;
+use OC\Log\Syslog;
+use OC\SystemConfig;
+use OCP\IConfig;
+use OCP\IServerContainer;
+use Test\TestCase;
+
+/**
+ * Class LogFactoryTest
+ *
+ * @package Test\Log
+ */
+class LogFactoryTest extends TestCase {
+ /** @var IServerContainer|\PHPUnit_Framework_MockObject_MockObject */
+ protected $c;
+
+ /** @var LogFactory */
+ protected $factory;
+
+ /** @var SystemConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $systemConfig;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->c = $this->createMock(IServerContainer::class);
+ $this->systemConfig = $this->createMock(SystemConfig::class);
+
+ $this->factory = new LogFactory($this->c, $this->systemConfig);
+ }
+
+ public function fileTypeProvider(): array {
+ return [
+ [
+ 'file'
+ ],
+ [
+ 'nextcloud'
+ ],
+ [
+ 'owncloud'
+ ],
+ [
+ 'krzxkyr_default'
+ ]
+ ];
+ }
+
+ /**
+ * @param string $type
+ * @dataProvider fileTypeProvider
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function testFile(string $type) {
+ $datadir = \OC::$SERVERROOT.'/data';
+ $defaultLog = $datadir . '/nextcloud.log';
+
+ $this->systemConfig->expects($this->exactly(2))
+ ->method('getValue')
+ ->withConsecutive(['datadirectory', $datadir], ['logfile', $defaultLog])
+ ->willReturnOnConsecutiveCalls($datadir, $defaultLog);
+
+ $log = $this->factory->get($type);
+ $this->assertInstanceOf(File::class, $log);
+ }
+
+ public function logFilePathProvider():array {
+ return [
+ [
+ '/dev/null',
+ '/dev/null'
+ ],
+ [
+ '/xdev/youshallfallback',
+ \OC::$SERVERROOT.'/data/nextcloud.log'
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider logFilePathProvider
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function testFileCustomPath($path, $expected) {
+ $datadir = \OC::$SERVERROOT.'/data';
+ $defaultLog = $datadir . '/nextcloud.log';
+
+ $this->systemConfig->expects($this->exactly(2))
+ ->method('getValue')
+ ->withConsecutive(['datadirectory', $datadir], ['logfile', $defaultLog])
+ ->willReturnOnConsecutiveCalls($datadir, $path);
+
+ $log = $this->factory->get('file');
+ $this->assertInstanceOf(File::class, $log);
+ $this->assertSame($expected, $log->getLogFilePath());
+ }
+
+ /**
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function testErrorLog() {
+ $log = $this->factory->get('errorlog');
+ $this->assertInstanceOf(Errorlog::class, $log);
+ }
+
+ /**
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function testSystemLog() {
+ $this->c->expects($this->once())
+ ->method('resolve')
+ ->with(Syslog::class)
+ ->willReturn($this->createMock(Syslog::class));
+
+ $log = $this->factory->get('syslog');
+ $this->assertInstanceOf(Syslog::class, $log);
+ }
+}
diff --git a/tests/lib/LoggerTest.php b/tests/lib/LoggerTest.php
index 6b9c9af8639..83cb87b8733 100644
--- a/tests/lib/LoggerTest.php
+++ b/tests/lib/LoggerTest.php
@@ -10,8 +10,9 @@ namespace Test;
use OC\Log;
use OCP\ILogger;
+use OCP\Log\IWriter;
-class LoggerTest extends TestCase {
+class LoggerTest extends TestCase implements IWriter {
/** @var \OC\SystemConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
@@ -23,15 +24,15 @@ class LoggerTest extends TestCase {
private $logger;
/** @var array */
- static private $logs = array();
+ private $logs = [];
protected function setUp() {
parent::setUp();
- self::$logs = array();
+ $this->logs = [];
$this->config = $this->createMock(\OC\SystemConfig::class);
$this->registry = $this->createMock(\OCP\Support\CrashReport\IRegistry::class);
- $this->logger = new Log('Test\LoggerTest', $this->config, null, $this->registry);
+ $this->logger = new Log($this, $this->config, null, $this->registry);
}
public function testInterpolation() {
@@ -63,11 +64,11 @@ class LoggerTest extends TestCase {
}
private function getLogs() {
- return self::$logs;
+ return $this->logs;
}
- public static function write($app, $message, $level) {
- self::$logs[]= "$level $message";
+ public function write(string $app, $message, int $level) {
+ $this->logs[]= "$level $message";
}
public function userAndPasswordData() {
@@ -202,23 +203,4 @@ class LoggerTest extends TestCase {
$this->assertContains('*** sensitive parameters replaced ***', $logLine);
}
}
-
- public function dataGetLogClass() {
- return [
- ['file', \OC\Log\File::class],
- ['errorlog', \OC\Log\Errorlog::class],
- ['syslog', \OC\Log\Syslog::class],
-
- ['owncloud', \OC\Log\File::class],
- ['nextcloud', \OC\Log\File::class],
- ['foobar', \OC\Log\File::class],
- ];
- }
-
- /**
- * @dataProvider dataGetLogClass
- */
- public function testGetLogClass($type, $class) {
- $this->assertEquals($class, Log::getLogClass($type));
- }
}