add Download logfile button to admin settings

add logSettingsController

add download logfile button

move getEntries to LogSettingsController

move set log level to logsettingscontroller.php

add warning if logfile is bigger than 100MB

add unit test for set log level

fix typecasting, add new line at EoF

show log and logfile download only if log_type is set to owncloud

add unit test for getFilenameForDownload
This commit is contained in:
Georg Ehrke 2014-12-20 22:44:41 +01:00
parent 510488ad3e
commit f579f2bd94
12 changed files with 297 additions and 51 deletions

View File

@ -111,7 +111,7 @@ class OC_Log_Owncloud {
$entriesCount = 0;
$lines = 0;
// Loop through each character of the file looking for new lines
while ($pos >= 0 && $entriesCount < $limit) {
while ($pos >= 0 && ($limit === null ||$entriesCount < $limit)) {
fseek($handle, $pos);
$ch = fgetc($handle);
if ($ch == "\n" || $pos == 0) {
@ -141,4 +141,11 @@ class OC_Log_Owncloud {
}
return $entries;
}
/**
* @return string
*/
public static function getLogFilePath() {
return self::$logFile;
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* @author Georg Ehrke
* @copyright 2014 Georg Ehrke <georg@ownCloud.com>
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCP\AppFramework\Http;
class DataDownloadResponse extends DownloadResponse {
/**
* @var string
*/
private $data;
/**
* Creates a response that prompts the user to download the text
* @param string $data text to be downloaded
* @param string $filename the name that the downloaded file should have
* @param string $contentType the mimetype that the downloaded file should have
*/
public function __construct($data, $filename, $contentType) {
$this->data = $data;
parent::__construct($filename, $contentType);
}
/**
* @param string $data
*/
public function setData($data) {
$this->data = $data;
}
/**
* @return string
*/
public function render() {
return $this->data;
}
}

View File

@ -10,8 +10,14 @@ OC_App::setActiveNavigationEntry("admin");
$template = new OC_Template('settings', 'admin', 'user');
$entries = OC_Log_Owncloud::getEntries(3);
$entriesRemaining = count(OC_Log_Owncloud::getEntries(4)) > 3;
$showLog = (\OC::$server->getConfig()->getSystemValue('log_type', 'owncloud') === 'owncloud');
$numEntriesToLoad = 3;
$entries = OC_Log_Owncloud::getEntries($numEntriesToLoad + 1);
$entriesRemaining = count($entries) > $numEntriesToLoad;
$entries = array_slice($entries, 0, $numEntriesToLoad);
$logFilePath = OC_Log_Owncloud::getLogFilePath();
$doesLogFileExist = file_exists($logFilePath);
$logFileSize = filesize($logFilePath);
$config = \OC::$server->getConfig();
$appConfig = \OC::$server->getAppConfig();
@ -31,6 +37,9 @@ $template->assign('mail_smtpname', $config->getSystemValue("mail_smtpname", ''))
$template->assign('mail_smtppassword', $config->getSystemValue("mail_smtppassword", ''));
$template->assign('entries', $entries);
$template->assign('entriesremain', $entriesRemaining);
$template->assign('logFileSize', $logFileSize);
$template->assign('doesLogFileExist', $doesLogFileExist);
$template->assign('showLog', $showLog);
$template->assign('readOnlyConfigEnabled', OC_Helper::isReadOnlyConfigEnabled());
$template->assign('isLocaleWorking', OC_Util::isSetLocaleWorking());
$template->assign('isPhpCharSetUtf8', OC_Util::isPhpCharSetUtf8());

View File

@ -1,21 +0,0 @@
<?php
/**
* Copyright (c) 2012, Robin Appelman <icewind1991@gmail.com>
* This file is licensed under the Affero General Public License version 3 or later.
* See the COPYING-README file.
*/
OC_JSON::checkAdminUser();
$count=(isset($_GET['count']))?$_GET['count']:50;
$offset=(isset($_GET['offset']))?$_GET['offset']:0;
$entries=OC_Log_Owncloud::getEntries($count, $offset);
$data = array();
OC_JSON::success(
array(
"data" => $entries,
"remain" => count(OC_Log_Owncloud::getEntries(1, $offset + $count)) !== 0,
)
);

View File

@ -1,13 +0,0 @@
<?php
/**
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
* This file is licensed under the Affero General Public License version 3 or later.
* See the COPYING-README file.
*/
OC_Util::checkAdminUser();
OCP\JSON::callCheck();
OC_Config::setValue( 'loglevel', $_POST['level'] );
echo 'true';

View File

@ -12,6 +12,7 @@ namespace OC\Settings;
use OC\Settings\Controller\AppSettingsController;
use OC\Settings\Controller\GroupsController;
use OC\Settings\Controller\LogSettingsController;
use OC\Settings\Controller\MailSettingsController;
use OC\Settings\Controller\SecuritySettingsController;
use OC\Settings\Controller\UsersController;
@ -91,6 +92,15 @@ class Application extends App {
$c->query('URLGenerator')
);
});
$container->registerService('LogSettingsController', function(IContainer $c) {
return new LogSettingsController(
$c->query('AppName'),
$c->query('Request'),
$c->query('Config'),
$c->query('L10N'),
$c->query('TimeFactory')
);
});
/**
* Middleware

View File

@ -0,0 +1,126 @@
<?php
/**
* @author Georg Ehrke
* @copyright 2014 Georg Ehrke <georg@ownCloud.com>
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Settings\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\IL10N;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCP\IConfig;
/**
* Class LogSettingsController
*
* @package OC\Settings\Controller
*/
class LogSettingsController extends Controller {
/**
* @var \OCP\IConfig
*/
private $config;
/**
* @var \OCP\IL10N
*/
private $l10n;
/**
* @var \OCP\ITimeFactory
*/
private $timefactory;
/**
* @param string $appName
* @param IRequest $request
* @param IConfig $config
*/
public function __construct($appName,
IRequest $request,
IConfig $config,
IL10N $l10n,
ITimeFactory $timeFactory) {
parent::__construct($appName, $request);
$this->config = $config;
$this->l10n = $l10n;
$this->timefactory = $timeFactory;
}
/**
* set log level for logger
*
* @param int $level
* @return JSONResponse
*/
public function setLogLevel($level) {
if ($level < 0 || $level > 4) {
return new JSONResponse([
'message' => (string) $this->l10n->t('log-level out of allowed range'),
], Http::STATUS_BAD_REQUEST);
}
$this->config->setSystemValue('loglevel', $level);
return new JSONResponse([
'level' => $level,
]);
}
/**
* get log entries from logfile
*
* @param int $count
* @param int $offset
* @return JSONResponse
*/
public function getEntries($count=50, $offset=0) {
return new JSONResponse([
'data' => \OC_Log_Owncloud::getEntries($count, $offset),
'remain' => count(\OC_Log_Owncloud::getEntries(1, $offset + $count)) !== 0,
]);
}
/**
* download logfile
*
* @NoCSRFRequired
*
* @return DataDownloadResponse
*/
public function download() {
return new DataDownloadResponse(
json_encode(\OC_Log_Owncloud::getEntries(null, null)),
$this->getFilenameForDownload(),
'application/json'
);
}
/**
* get filename for the logfile that's being downloaded
*
* @param int $timestamp (defaults to time())
* @return string
*/
private function getFilenameForDownload($timestamp=null) {
$instanceId = $this->config->getSystemValue('instanceid');
$filename = implode([
'ownCloud',
$instanceId,
(!is_null($timestamp)) ? $timestamp : $this->timefactory->getTime()
], '-');
$filename .= '.log';
return $filename;
}
}

View File

@ -34,7 +34,7 @@ $(document).ready(function(){
$('#loglevel').change(function(){
$.post(OC.filePath('settings','ajax','setloglevel.php'), { level: $(this).val() },function(){
$.post(OC.generateUrl('/settings/admin/log/level'), {level: $(this).val()},function(){
OC.Log.reload();
} );
});

View File

@ -20,14 +20,12 @@ OC.Log = {
loaded: 3,//are initially loaded
getMore: function (count) {
count = count || 10;
$.get(OC.filePath('settings', 'ajax', 'getlog.php'), {offset: OC.Log.loaded, count: count}, function (result) {
if (result.status === 'success') {
OC.Log.addEntries(result.data);
if (!result.remain) {
$('#moreLog').hide();
}
$('#lessLog').show();
$.get(OC.generateUrl('/settings/admin/log/entries'), {offset: OC.Log.loaded, count: count}, function (result) {
OC.Log.addEntries(result.data);
if (!result.remain) {
$('#moreLog').hide();
}
$('#lessLog').show();
});
},
showLess: function (count) {

View File

@ -14,7 +14,7 @@ $application->registerRoutes($this, array(
'groups' => array('url' => '/settings/users/groups'),
'users' => array('url' => '/settings/users/users')
),
'routes' =>array(
'routes' => array(
array('name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST'),
array('name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST'),
array('name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'),
@ -24,6 +24,9 @@ $application->registerRoutes($this, array(
array('name' => 'SecuritySettings#enforceSSLForSubdomains', 'url' => '/settings/admin/security/ssl/subdomains', 'verb' => 'POST'),
array('name' => 'SecuritySettings#trustedDomains', 'url' => '/settings/admin/security/trustedDomains', 'verb' => 'POST'),
array('name' => 'Users#setMailAddress', 'url' => '/settings/users/{id}/mailAddress', 'verb' => 'PUT'),
array('name' => 'LogSettings#setLogLevel', 'url' => '/settings/admin/log/level', 'verb' => 'POST'),
array('name' => 'LogSettings#getEntries', 'url' => '/settings/admin/log/entries', 'verb' => 'GET'),
array('name' => 'LogSettings#download', 'url' => '/settings/admin/log/download', 'verb' => 'GET'),
)
));
@ -87,10 +90,6 @@ $this->create('settings_ajax_uninstallapp', '/settings/ajax/uninstallapp.php')
$this->create('settings_ajax_navigationdetect', '/settings/ajax/navigationdetect.php')
->actionInclude('settings/ajax/navigationdetect.php');
// admin
$this->create('settings_ajax_getlog', '/settings/ajax/getlog.php')
->actionInclude('settings/ajax/getlog.php');
$this->create('settings_ajax_setloglevel', '/settings/ajax/setloglevel.php')
->actionInclude('settings/ajax/setloglevel.php');
$this->create('settings_ajax_excludegroups', '/settings/ajax/excludegroups.php')
->actionInclude('settings/ajax/excludegroups.php');
$this->create('settings_ajax_checksetup', '/settings/ajax/checksetup')

View File

@ -462,6 +462,7 @@ if ($_['suggestedOverwriteWebroot']) {
<option value='<?php p($i)?>' <?php p($selected) ?>><?php p($levelLabels[$i])?></option>
<?php endfor;?>
</select>
<?php if ($_['showLog'] && $_['doesLogFileExist']): ?>
<table id="log" class="grid">
<?php foreach ($_['entries'] as $entry): ?>
<tr>
@ -484,11 +485,20 @@ if ($_['suggestedOverwriteWebroot']) {
</tr>
<?php endforeach;?>
</table>
<?php if ($_['logFileSize'] > 0): ?>
<a href="<?php print_unescaped(OC::$server->getURLGenerator()->linkToRoute('settings.LogSettings.download')); ?>" class="button" id="downloadLog"><?php p($l->t('Download logfile'));?></a>
<?php endif; ?>
<?php if ($_['entriesremain']): ?>
<input id="moreLog" type="button" value="<?php p($l->t('More'));?>...">
<input id="lessLog" type="button" value="<?php p($l->t('Less'));?>...">
<?php endif; ?>
<?php if ($_['logFileSize'] > (100 * 1024 * 1024)): ?>
<br>
<em>
<?php p($l->t('The logfile is bigger than 100MB. Downloading it may take some time!')); ?>
</em>
<?php endif; ?>
<?php endif; ?>
</div>
<div class="section">

View File

@ -0,0 +1,79 @@
<?php
/**
* @author Georg Ehrke
* @copyright 2014 Georg Ehrke <georg@ownCloud.com>
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace Test\Settings\Controller;
use \OC\Settings\Application;
/**
* @package OC\Settings\Controller
*/
class LogSettingsControllerTest extends \Test\TestCase {
/** @var \OCP\AppFramework\IAppContainer */
private $container;
/** @var LogSettingsController */
private $logSettingsController;
protected function setUp() {
$app = new Application();
$this->container = $app->getContainer();
$this->container['Config'] = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()->getMock();
$this->container['AppName'] = 'settings';
$this->logSettingsController = $this->container['LogSettingsController'];
}
/**
* @dataProvider logLevelData
*/
public function testSetLogLevel($level, $inRange) {
if ($inRange) {
$this->container['Config']
->expects($this->once())
->method('setSystemValue')
->with('loglevel', $level);
}
$response = $this->logSettingsController->setLogLevel($level)->getData();
if ($inRange) {
$expectedResponse = ['level' => $level];
} else {
$expectedResponse = ['message' => 'log-level out of allowed range'];
}
$this->assertSame($expectedResponse, $response);
}
public function logLevelData() {
return [
[-1, false],
[0, true],
[1, true],
[2, true],
[3, true],
[4, true],
[5, false],
];
}
public function testGetFilenameForDownload() {
$timestamp = 42;
$this->container['Config']
->expects($this->once())
->method('getSystemValue')
->with('instanceid')
->will($this->returnValue('0xF'));
$filename = \Test_Helper::invokePrivate($this->logSettingsController, 'getFilenameForDownload', [$timestamp]);
$this->assertSame('ownCloud-0xF-42.log', $filename);
}
}