From 0ecde6ce23ad8ee6132797de11e004e7458a83fd Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 13:25:46 +0200 Subject: [PATCH 1/7] central logging mechanism This introduces a logger mechanism and a new data/log directory. This is a first proof of concept. It's built on top of the new global error handling mechanism Things to discuss: * should we adopt PSR-3 somehow? if yes, how and should plugins be able to drop-in other psr3 loggers? * how to configure which facilities shall be logged? * should we implement a log deletion feature? * is the log format sensible? * should we implement a log viewer admin plugin? * should logging trigger events (it should maybe replace the deprecation event) --- inc/Debug/DebugHelper.php | 3 +- inc/ErrorHandler.php | 20 ++++----- inc/Extension/Event.php | 8 +++- inc/Logger.php | 87 +++++++++++++++++++++++++++++++++++++++ inc/infoutils.php | 20 ++++----- inc/init.php | 23 ++++++----- 6 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 inc/Logger.php diff --git a/inc/Debug/DebugHelper.php b/inc/Debug/DebugHelper.php index 09ff76b0f..3f83b7a17 100644 --- a/inc/Debug/DebugHelper.php +++ b/inc/Debug/DebugHelper.php @@ -5,6 +5,7 @@ namespace dokuwiki\Debug; use Doku_Event; use dokuwiki\Extension\EventHandler; +use dokuwiki\Logger; class DebugHelper { @@ -160,7 +161,7 @@ class DebugHelper if ($event->data['alternative']) { $msg .= ' ' . $event->data['alternative'] . ' should be used instead!'; } - dbglog($msg); + Logger::getInstance(Logger::LOG_DEPRECATED)->log($msg); } $event->advise_after(); } diff --git a/inc/ErrorHandler.php b/inc/ErrorHandler.php index 184caaebb..ae0e5db2b 100644 --- a/inc/ErrorHandler.php +++ b/inc/ErrorHandler.php @@ -36,7 +36,7 @@ class ErrorHandler $msg = 'An unforeseen error has occured. This is most likely a bug somewhere.'; if ($plugin) $msg .= ' It might be a problem in the ' . $plugin . ' plugin.'; $logged = self::logException($e) - ? 'More info has been written to the DokuWiki _error.log' + ? 'More info has been written to the DokuWiki error log.' : $e->getFile() . ':' . $e->getLine(); echo <<' . hsc(get_class($e) . ': ' . $e->getMessage()); - if (self::logException($e)) $msg .= '
More info is available in the _error.log'; + if (self::logException($e)) $msg .= '
More info is available in the error log.'; msg($msg, -1); } @@ -100,16 +100,12 @@ EOT; */ public static function logException($e) { - global $conf; - - $log = join("\t", [ - gmdate('c'), - get_class($e), - $e->getFile() . '(' . $e->getLine() . ')', - $e->getMessage(), - ]) . "\n"; - $log .= $e->getTraceAsString() . "\n"; - return io_saveFile($conf['cachedir'] . '/_error.log', $log, true); + return Logger::getInstance()->log( + get_class($e) . ': ' . $e->getMessage(), + $e->getTraceAsString(), + $e->getFile(), + $e->getLine() + ); } /** diff --git a/inc/Extension/Event.php b/inc/Extension/Event.php index 32f346c72..cc38f0f36 100644 --- a/inc/Extension/Event.php +++ b/inc/Extension/Event.php @@ -3,6 +3,8 @@ namespace dokuwiki\Extension; +use dokuwiki\Logger; + /** * The Action plugin event */ @@ -71,7 +73,8 @@ class Event if ($EVENT_HANDLER !== null) { $EVENT_HANDLER->process_event($this, 'BEFORE'); } else { - dbglog($this->name . ':BEFORE event triggered before event system was initialized'); + Logger::getInstance(Logger::LOG_DEBUG) + ->log($this->name . ':BEFORE event triggered before event system was initialized'); } return (!$enablePreventDefault || $this->runDefault); @@ -92,7 +95,8 @@ class Event if ($EVENT_HANDLER !== null) { $EVENT_HANDLER->process_event($this, 'AFTER'); } else { - dbglog($this->name . ':AFTER event triggered before event system was initialized'); + Logger::getInstance(Logger::LOG_DEBUG)-> + log($this->name . ':AFTER event triggered before event system was initialized'); } } diff --git a/inc/Logger.php b/inc/Logger.php new file mode 100644 index 000000000..3ff1d59b9 --- /dev/null +++ b/inc/Logger.php @@ -0,0 +1,87 @@ +facility = $facility; + } + + /** + * Return a Logger instance for the given facility + * + * @param string $facility The type of log + * @return Logger + */ + static public function getInstance($facility = self::LOG_ERROR) + { + if (self::$instances[$facility] === null) { + self::$instances[$facility] = new Logger($facility); + } + return self::$instances[$facility]; + } + + /** + * Log a message to the facility log + * + * @param string $message The log message + * @param mixed $details Any details that should be added to the log entry + * @param string $file A source filename if this is related to a source position + * @param int $line A line number for the above file + * @return bool + */ + public function log($message, $details = null, $file = '', $line = 0) + { + // details are logged indented + if ($details && !is_string($details)) { + $details = json_encode($details, JSON_PRETTY_PRINT); + $details = explode("\n", $details); + $loglines = array_map(function ($line) { + return ' ' . $line; + }, $details); + } elseif ($details) { + $loglines = [$details]; + } else { + $loglines = []; + } + + $logline = gmdate('c') . "\t" . $message; + if ($file) { + $logline .= "\t$file"; + if ($line) $logline .= "($line)"; + } + + array_unshift($loglines, $logline); + return $this->writeLogLines($loglines); + } + + /** + * Write the given lines to today's facility log + * + * @param string[] $lines the raw lines to append to the log + * @return bool true if the log was written + */ + protected function writeLogLines($lines) + { + global $conf; + $logfile = $conf['logdir'] . '/' . $this->facility . '/' . gmdate('Y-m-d') . '.log'; + return io_saveFile($logfile, join("\n", $lines) . "\n", true); + } +} diff --git a/inc/infoutils.php b/inc/infoutils.php index a94442082..6c69b34ba 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -424,14 +424,13 @@ function dbg($msg,$hidden=false){ * Print info to a log file * * @author Andreas Gohr - * + * @deprecated 2020-08-13 * @param string $msg * @param string $header */ function dbglog($msg,$header=''){ global $conf; - /* @var Input $INPUT */ - global $INPUT; + dbg_deprecated('\\dokuwiki\\Logger'); // The debug log isn't automatically cleaned thus only write it when // debugging has been enabled by the user. @@ -440,14 +439,15 @@ function dbglog($msg,$header=''){ $msg = print_r($msg,true); } - if($header) $msg = "$header\n$msg"; - - $file = $conf['cachedir'].'/debug.log'; - $fh = fopen($file,'a'); - if($fh){ - fwrite($fh,date('H:i:s ').$INPUT->server->str('REMOTE_ADDR').': '.$msg."\n"); - fclose($fh); + // was the msg as single line string? use it as header + if($header === '' && strpos($msg, "\n") === false) { + $header = $msg; + $msg = ''; } + + \dokuwiki\Logger::getInstance(\dokuwiki\Logger::LOG_DEBUG)->log( + $header, $msg + ); } /** diff --git a/inc/init.php b/inc/init.php index f4ca7e8d4..5cf1b56e9 100644 --- a/inc/init.php +++ b/inc/init.php @@ -269,16 +269,19 @@ function init_session() { function init_paths(){ global $conf; - $paths = array('datadir' => 'pages', - 'olddir' => 'attic', - 'mediadir' => 'media', - 'mediaolddir' => 'media_attic', - 'metadir' => 'meta', - 'mediametadir' => 'media_meta', - 'cachedir' => 'cache', - 'indexdir' => 'index', - 'lockdir' => 'locks', - 'tmpdir' => 'tmp'); + $paths = [ + 'datadir' => 'pages', + 'olddir' => 'attic', + 'mediadir' => 'media', + 'mediaolddir' => 'media_attic', + 'metadir' => 'meta', + 'mediametadir' => 'media_meta', + 'cachedir' => 'cache', + 'indexdir' => 'index', + 'lockdir' => 'locks', + 'tmpdir' => 'tmp', + 'logdir' => 'log', + ]; foreach($paths as $c => $p) { $path = empty($conf[$c]) ? $conf['savedir'].'/'.$p : $conf[$c]; From 5b784a2b834405d28627b116e3d44b7d16fc1840 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 13:52:35 +0200 Subject: [PATCH 2/7] added log dir to git --- data/log/_dummy | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/log/_dummy diff --git a/data/log/_dummy b/data/log/_dummy new file mode 100644 index 000000000..e492265be --- /dev/null +++ b/data/log/_dummy @@ -0,0 +1 @@ +You can safely delete this file. \ No newline at end of file From 70cc2cbf41ee65a6048aab5aab40e124b337e295 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 19:48:45 +0200 Subject: [PATCH 3/7] added logviwer admin plugin This allows for easy viewing of the available logs. The log format was sligthly adjusted again for easier parsing. --- .gitignore | 1 + inc/Logger.php | 31 ++++- inc/Ui/Admin.php | 2 +- lib/plugins/extension/helper/extension.php | 2 +- lib/plugins/logviewer/admin.php | 152 +++++++++++++++++++++ lib/plugins/logviewer/admin.svg | 1 + lib/plugins/logviewer/lang/en/intro.txt | 8 ++ lib/plugins/logviewer/lang/en/lang.php | 9 ++ lib/plugins/logviewer/lang/en/nolog.txt | 1 + lib/plugins/logviewer/plugin.info.txt | 7 + lib/plugins/logviewer/script.js | 8 ++ lib/plugins/logviewer/style.less | 41 ++++++ lib/scripts/behaviour.js | 9 +- 13 files changed, 261 insertions(+), 11 deletions(-) create mode 100644 lib/plugins/logviewer/admin.php create mode 100644 lib/plugins/logviewer/admin.svg create mode 100644 lib/plugins/logviewer/lang/en/intro.txt create mode 100644 lib/plugins/logviewer/lang/en/lang.php create mode 100644 lib/plugins/logviewer/lang/en/nolog.txt create mode 100644 lib/plugins/logviewer/plugin.info.txt create mode 100644 lib/plugins/logviewer/script.js create mode 100644 lib/plugins/logviewer/style.less diff --git a/.gitignore b/.gitignore index a2e2107b1..de576886a 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ !/lib/plugins/styling !/lib/plugins/testing !/lib/plugins/usermanager +!/lib/plugins/logviewer !/lib/plugins/action.php !/lib/plugins/admin.php !/lib/plugins/auth.php diff --git a/inc/Logger.php b/inc/Logger.php index 3ff1d59b9..0ada6d63e 100644 --- a/inc/Logger.php +++ b/inc/Logger.php @@ -50,8 +50,10 @@ class Logger public function log($message, $details = null, $file = '', $line = 0) { // details are logged indented - if ($details && !is_string($details)) { - $details = json_encode($details, JSON_PRETTY_PRINT); + if ($details) { + if (!is_string($details)) { + $details = json_encode($details, JSON_PRETTY_PRINT); + } $details = explode("\n", $details); $loglines = array_map(function ($line) { return ' ' . $line; @@ -62,16 +64,34 @@ class Logger $loglines = []; } - $logline = gmdate('c') . "\t" . $message; + // datetime, fileline, message + $logline = gmdate('Y-m-d H:i:s') . "\t"; if ($file) { - $logline .= "\t$file"; + $logline .= $file; if ($line) $logline .= "($line)"; } + $logline .= "\t" . $message; array_unshift($loglines, $logline); return $this->writeLogLines($loglines); } + /** + * Construct the log file for the given day + * + * @param false|string|int $date Date to access, false for today + * @return string + */ + public function getLogfile($date = false) + { + global $conf; + + if ($date !== null) $date = strtotime($date); + if (!$date) $date = time(); + + return $conf['logdir'] . '/' . $this->facility . '/' . date('Y-m-d', $date) . '.log'; + } + /** * Write the given lines to today's facility log * @@ -80,8 +100,7 @@ class Logger */ protected function writeLogLines($lines) { - global $conf; - $logfile = $conf['logdir'] . '/' . $this->facility . '/' . gmdate('Y-m-d') . '.log'; + $logfile = $this->getLogfile(); return io_saveFile($logfile, join("\n", $lines) . "\n", true); } } diff --git a/inc/Ui/Admin.php b/inc/Ui/Admin.php index fe319d414..04d8da5ec 100644 --- a/inc/Ui/Admin.php +++ b/inc/Ui/Admin.php @@ -12,7 +12,7 @@ namespace dokuwiki\Ui; */ class Admin extends Ui { - protected $forAdmins = array('usermanager', 'acl', 'extension', 'config', 'styling'); + protected $forAdmins = array('usermanager', 'acl', 'extension', 'config', 'logviewer', 'styling'); protected $forManagers = array('revert', 'popularity'); /** @var array[] */ protected $menu; diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 5ddf3323e..eabcd3ac1 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -128,7 +128,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin array( 'authad', 'authldap', 'authpdo', 'authplain', 'acl', 'config', 'extension', 'info', 'popularity', 'revert', - 'safefnrecode', 'styling', 'testing', 'usermanager', + 'safefnrecode', 'styling', 'testing', 'usermanager', 'logviewer', 'template:dokuwiki', ) ); diff --git a/lib/plugins/logviewer/admin.php b/lib/plugins/logviewer/admin.php new file mode 100644 index 000000000..7a28e208b --- /dev/null +++ b/lib/plugins/logviewer/admin.php @@ -0,0 +1,152 @@ + + */ +class admin_plugin_logviewer extends DokuWiki_Admin_Plugin +{ + + protected $facilities; + protected $facility; + protected $date; + + /** @inheritDoc */ + public function forAdminOnly() + { + return true; + } + + /** @inheritDoc */ + public function handle() + { + global $INPUT; + + $this->facilities = $this->getFacilities(); + $this->facility = $INPUT->str('facility'); + if (!in_array($this->facility, $this->facilities)) { + $this->facility = $this->facilities[0]; + } + + $this->date = $INPUT->str('date'); + if (!preg_match('/^\d\d\d\d-\d\d-\d\d$/', $this->date)) { + $this->date = gmdate('Y-m-d'); + } + } + + /** @inheritDoc */ + public function html() + { + echo '
'; + echo $this->locale_xhtml('intro'); + $this->displayTabs(); + $this->displayLog(); + echo '
'; + } + + /** + * Show the navigational tabs and date picker + */ + protected function displayTabs() + { + global $ID; + + $form = new dokuwiki\Form\Form(['method'=>'GET']); + $form->setHiddenField('do', 'admin'); + $form->setHiddenField('page', 'logviewer'); + $form->setHiddenField('facility', $this->facility); + $form->addTextInput('date','Date*')->attr('type','date')->val($this->date)->addClass('quickselect'); + $form->addButton('submit','>')->attr('type','submit'); + echo $form->toHTML(); + + echo '
    '; + foreach ($this->facilities as $facility) { + echo '
  • '; + if ($facility == $this->facility) { + echo '' . hsc($facility) . ''; + } else { + $link = wl($ID, + ['do' => 'admin', 'page' => 'logviewer', 'date' => $this->date, 'facility' => $facility]); + echo '' . hsc($facility) . ''; + } + echo '
  • '; + } + echo '
'; + + } + + /** + * Output the logfile contents + */ + protected function displayLog() + { + $logfile = Logger::getInstance($this->facility)->getLogfile($this->date); + if (!file_exists($logfile)) { + echo $this->locale_xhtml('nolog'); + return; + } + + // loop through the file an print it + echo '
'; + $lines = file($logfile); + $cnt = count($lines); + for ($i = 0; $i < $cnt; $i++) { + $line = $lines[$i]; + + if ($line[0] === ' ' && $line[1] === ' ') { + // lines indented by two spaces are details, aggregate them + echo '
'; + while ($line[0] === ' ' && $line[1] === ' ') { + echo hsc(substr($line, 2)) . '
'; + $line = $lines[$i++]; + } + echo '
'; + $i -= 2; // rewind the counter + } else { + // other lines are actual log lines in three parts + list($dt, $file, $msg) = explode("\t", $line, 3); + echo '
'; + echo '' . hsc($dt) . ''; + echo ''; + echo '' . hsc($msg) . ''; + echo '' . hsc($file) . ''; + echo ''; + echo '
'; + } + } + echo '
'; + } + + /** + * Get the available logging facilities + * + * @return array + */ + protected function getFacilities() + { + global $conf; + $conf['logdir']; + + // default facilities first + $facilities = [ + Logger::LOG_ERROR, + Logger::LOG_DEPRECATED, + Logger::LOG_DEBUG, + ]; + + // add all other dirs + $dirs = glob($conf['logdir'] . '/*', GLOB_ONLYDIR); + foreach ($dirs as $dir) { + $facilities[] = basename($dir); + } + $facilities = array_unique($facilities); + + return $facilities; + } + +} + diff --git a/lib/plugins/logviewer/admin.svg b/lib/plugins/logviewer/admin.svg new file mode 100644 index 000000000..3eb481759 --- /dev/null +++ b/lib/plugins/logviewer/admin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/plugins/logviewer/lang/en/intro.txt b/lib/plugins/logviewer/lang/en/intro.txt new file mode 100644 index 000000000..f3b488ec4 --- /dev/null +++ b/lib/plugins/logviewer/lang/en/intro.txt @@ -0,0 +1,8 @@ +====== View Logs ====== + +This interface allows you to view the various logs that are written by DokuWiki. By default, there shouldn't be logged +much here (it depends on your log settings). However if something goes wrong, chances are high, you'll find useful info +here. All times are UTC! + +Please be aware **log files can contain sensitive information** like passwords, paths or other secrets. +Be sure to redact the logs appropriately when posting them on the forum or in bug reports! diff --git a/lib/plugins/logviewer/lang/en/lang.php b/lib/plugins/logviewer/lang/en/lang.php new file mode 100644 index 000000000..3f32e0bed --- /dev/null +++ b/lib/plugins/logviewer/lang/en/lang.php @@ -0,0 +1,9 @@ + + */ + +$lang['menu'] = 'View Logs'; + diff --git a/lib/plugins/logviewer/lang/en/nolog.txt b/lib/plugins/logviewer/lang/en/nolog.txt new file mode 100644 index 000000000..2bdefff0c --- /dev/null +++ b/lib/plugins/logviewer/lang/en/nolog.txt @@ -0,0 +1 @@ +There are no log entries for the selected day and log facility. diff --git a/lib/plugins/logviewer/plugin.info.txt b/lib/plugins/logviewer/plugin.info.txt new file mode 100644 index 000000000..d18a82c21 --- /dev/null +++ b/lib/plugins/logviewer/plugin.info.txt @@ -0,0 +1,7 @@ +base logviewer +author Andreas Gohr +email andi@splitbrain.org +date 2020-08-13 +name logviewer plugin +desc View DokuWiki logs +url https://www.dokuwiki.org/plugin:logviewer diff --git a/lib/plugins/logviewer/script.js b/lib/plugins/logviewer/script.js new file mode 100644 index 000000000..5a5303c84 --- /dev/null +++ b/lib/plugins/logviewer/script.js @@ -0,0 +1,8 @@ +/** + * Scroll to the end of the log on load + */ +jQuery(function () { + var $dl = jQuery('#plugin__logviewer').find('dl'); + if(!$dl.length) return; + $dl.animate({ scrollTop: $dl.prop("scrollHeight")}, 500); +}); diff --git a/lib/plugins/logviewer/style.less b/lib/plugins/logviewer/style.less new file mode 100644 index 000000000..f9c8b1d89 --- /dev/null +++ b/lib/plugins/logviewer/style.less @@ -0,0 +1,41 @@ +#plugin__logviewer { + form { + float: right; + } + + .tabs { + margin-bottom: 2em; + } + + dl { + max-height: 80vh; + overflow: auto; + + dt { + display: flex; + + .datetime { + flex: 0 0 auto; + margin-right: 1em; + } + + .log { + flex: 1 1 auto; + + span { + display: block; + } + + span.file { + font-family: monospace; + } + } + } + + dd { + font-size: 80%; + white-space: nowrap; + font-family: monospace; + } + } +} diff --git a/lib/scripts/behaviour.js b/lib/scripts/behaviour.js index f9aad3d02..968d2dd5f 100644 --- a/lib/scripts/behaviour.js +++ b/lib/scripts/behaviour.js @@ -102,15 +102,18 @@ var dw_behaviour = { /** * Autosubmit quick select forms * - * When a or tag has the class "quickselect", this script will * automatically submit its parent form when the select value changes. * It also hides the submit button of the form. * + * This includes a workaround a weird behaviour when the submit button has a name + * + * @link https://trackjs.com/blog/when-form-submit-is-not-a-function/ * @author Andreas Gohr */ quickSelect: function(){ - jQuery('select.quickselect') - .on('change', function(e){ e.target.form.submit(); }) + jQuery('.quickselect') + .change(function(e){ HTMLFormElement.prototype.submit.call(e.target.form); }) .closest('form').find(':button').not('.show').hide(); }, From c2050393228b5814b1f89804a01f19ad90502ce7 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 20:03:41 +0200 Subject: [PATCH 4/7] added convenience methods to log to our default facilities --- inc/Logger.php | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/inc/Logger.php b/inc/Logger.php index 0ada6d63e..345f8a28c 100644 --- a/inc/Logger.php +++ b/inc/Logger.php @@ -38,6 +38,54 @@ class Logger return self::$instances[$facility]; } + /** + * Convenience method to directly log to the error log + * + * @param string $message The log message + * @param mixed $details Any details that should be added to the log entry + * @param string $file A source filename if this is related to a source position + * @param int $line A line number for the above file + * @return bool + */ + static public function error($message, $details = null, $file = '', $line = 0) + { + return self::getInstance(self::LOG_ERROR)->log( + $message, $details, $file, $line + ); + } + + /** + * Convenience method to directly log to the debug log + * + * @param string $message The log message + * @param mixed $details Any details that should be added to the log entry + * @param string $file A source filename if this is related to a source position + * @param int $line A line number for the above file + * @return bool + */ + static public function debug($message, $details = null, $file = '', $line = 0) + { + return self::getInstance(self::LOG_DEBUG)->log( + $message, $details, $file, $line + ); + } + + /** + * Convenience method to directly log to the deprecation log + * + * @param string $message The log message + * @param mixed $details Any details that should be added to the log entry + * @param string $file A source filename if this is related to a source position + * @param int $line A line number for the above file + * @return bool + */ + static public function deprecated($message, $details = null, $file = '', $line = 0) + { + return self::getInstance(self::LOG_DEPRECATED)->log( + $message, $details, $file, $line + ); + } + /** * Log a message to the facility log * From 31667ec67823633de149106f2f0de3f1dbc5fd1e Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 20:04:34 +0200 Subject: [PATCH 5/7] replaced out calls to dbglog with new Logger calls --- inc/Sitemap/Mapper.php | 14 ++++++++------ inc/infoutils.php | 9 +++++---- lib/plugins/authad/auth.php | 4 +++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/inc/Sitemap/Mapper.php b/inc/Sitemap/Mapper.php index 2f0567f05..ae0c56427 100644 --- a/inc/Sitemap/Mapper.php +++ b/inc/Sitemap/Mapper.php @@ -9,6 +9,7 @@ namespace dokuwiki\Sitemap; use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Logger; /** * A class for building sitemaps and pinging search engines with the sitemap URL. @@ -43,14 +44,14 @@ class Mapper { if(@filesize($sitemap) && @filemtime($sitemap) > (time()-($conf['sitemap']*86400))){ // 60*60*24=86400 - dbglog('Sitemapper::generate(): Sitemap up to date'); + Logger::debug('Sitemapper::generate(): Sitemap up to date'); return false; } - dbglog("Sitemapper::generate(): using $sitemap"); + Logger::debug("Sitemapper::generate(): using $sitemap"); $pages = idx_get_indexer()->getPages(); - dbglog('Sitemapper::generate(): creating sitemap using '.count($pages).' pages'); + Logger::debug('Sitemapper::generate(): creating sitemap using '.count($pages).' pages'); $items = array(); // build the sitemap items @@ -150,10 +151,11 @@ class Mapper { $event = new \dokuwiki\Extension\Event('SITEMAP_PING', $data); if ($event->advise_before(true)) { foreach ($data['ping_urls'] as $name => $url) { - dbglog("Sitemapper::PingSearchEngines(): pinging $name"); + Logger::debug("Sitemapper::PingSearchEngines(): pinging $name"); $resp = $http->get($url); - if($http->error) dbglog("Sitemapper:pingSearchengines(): $http->error"); - dbglog('Sitemapper:pingSearchengines(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp))); + if($http->error) { + Logger::debug("Sitemapper:pingSearchengines(): $http->error", $resp); + } } } $event->advise_after(); diff --git a/inc/infoutils.php b/inc/infoutils.php index 6c69b34ba..e80bae63c 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -7,6 +7,7 @@ */ use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Logger; if(!defined('DOKU_MESSAGEURL')){ if(in_array('ssl', stream_get_transports())) { @@ -35,7 +36,7 @@ function checkUpdateMessages(){ // check if new messages needs to be fetched if($lm < time()-(60*60*24) || $lm < @filemtime(DOKU_INC.DOKU_SCRIPT)){ @touch($cf); - dbglog("checkUpdateMessages(): downloading messages to ".$cf.($is_http?' (without SSL)':' (with SSL)')); + Logger::debug("checkUpdateMessages(): downloading messages to ".$cf.($is_http?' (without SSL)':' (with SSL)')); $http = new DokuHTTPClient(); $http->timeout = 12; $resp = $http->get(DOKU_MESSAGEURL.$updateVersion); @@ -44,10 +45,10 @@ function checkUpdateMessages(){ // or it looks like one of our messages, not WiFi login or other interposed response io_saveFile($cf,$resp); } else { - dbglog("checkUpdateMessages(): unexpected HTTP response received"); + Logger::debug("checkUpdateMessages(): unexpected HTTP response received", $http->error); } }else{ - dbglog("checkUpdateMessages(): messages up to date"); + Logger::debug("checkUpdateMessages(): messages up to date"); } $data = io_readFile($cf); @@ -445,7 +446,7 @@ function dbglog($msg,$header=''){ $msg = ''; } - \dokuwiki\Logger::getInstance(\dokuwiki\Logger::LOG_DEBUG)->log( + Logger::getInstance(Logger::LOG_DEBUG)->log( $header, $msg ); } diff --git a/lib/plugins/authad/auth.php b/lib/plugins/authad/auth.php index 27a6b229e..442e6e3a8 100644 --- a/lib/plugins/authad/auth.php +++ b/lib/plugins/authad/auth.php @@ -1,5 +1,7 @@ initAdLdap(null); if (!$adldap) { - dbglog("authad/auth.php getUserCount(): _adldap not set."); + Logger::debug("authad/auth.php getUserCount(): _adldap not set."); return -1; } if ($filter == array()) { From cad4fbf6e21bd4a053f1f42b9e40c74f1cfaeab6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 13 Aug 2020 20:28:52 +0200 Subject: [PATCH 6/7] added logging configuration Log facitlities can now be disabled. By default only debug is disabled. It might make sense to by default disable deprecated as well? Debug logging is now independend of the allowdebug method. allowdebug was often used in two ways: for displaying errors directly to the user and for logging to the debug log. Now it only controls the former. --- conf/dokuwiki.php | 1 + inc/Logger.php | 18 ++++++++++++++---- inc/infoutils.php | 12 ++---------- lib/plugins/config/lang/en/lang.php | 1 + .../config/settings/config.metadata.php | 8 ++++++++ lib/plugins/logviewer/lang/en/intro.txt | 4 ++-- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/conf/dokuwiki.php b/conf/dokuwiki.php index 290453d89..0ec010715 100644 --- a/conf/dokuwiki.php +++ b/conf/dokuwiki.php @@ -111,6 +111,7 @@ $conf['mailfrom'] = ''; //use this email when sending mails $conf['mailreturnpath'] = ''; //use this email as returnpath for bounce mails $conf['mailprefix'] = ''; //use this as prefix of outgoing mails $conf['htmlmail'] = 1; //send HTML multipart mails +$conf['dontlog'] = 'debug'; //logging facilites that should be disabled /* Syndication Settings */ $conf['sitemap'] = 0; //Create a google sitemap? How often? In days. diff --git a/inc/Logger.php b/inc/Logger.php index 345f8a28c..5923777df 100644 --- a/inc/Logger.php +++ b/inc/Logger.php @@ -14,6 +14,8 @@ class Logger /** @var string what kind of log is this */ protected $facility; + protected $isLogging = true; + /** * Logger constructor. * @@ -21,7 +23,13 @@ class Logger */ protected function __construct($facility) { + global $conf; $this->facility = $facility; + + // Should logging be disabled for this facility? + $dontlog = explode(',', $conf['dontlog']); + $dontlog = array_map('trim', $dontlog); + if (in_array($facility, $dontlog)) $this->isLogging = false; } /** @@ -45,7 +53,7 @@ class Logger * @param mixed $details Any details that should be added to the log entry * @param string $file A source filename if this is related to a source position * @param int $line A line number for the above file - * @return bool + * @return bool has a log been written? */ static public function error($message, $details = null, $file = '', $line = 0) { @@ -61,7 +69,7 @@ class Logger * @param mixed $details Any details that should be added to the log entry * @param string $file A source filename if this is related to a source position * @param int $line A line number for the above file - * @return bool + * @return bool has a log been written? */ static public function debug($message, $details = null, $file = '', $line = 0) { @@ -77,7 +85,7 @@ class Logger * @param mixed $details Any details that should be added to the log entry * @param string $file A source filename if this is related to a source position * @param int $line A line number for the above file - * @return bool + * @return bool has a log been written? */ static public function deprecated($message, $details = null, $file = '', $line = 0) { @@ -93,10 +101,12 @@ class Logger * @param mixed $details Any details that should be added to the log entry * @param string $file A source filename if this is related to a source position * @param int $line A line number for the above file - * @return bool + * @return bool has a log been written? */ public function log($message, $details = null, $file = '', $line = 0) { + if(!$this->isLogging) return false; + // details are logged indented if ($details) { if (!is_string($details)) { diff --git a/inc/infoutils.php b/inc/infoutils.php index e80bae63c..f16d2264b 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -422,7 +422,7 @@ function dbg($msg,$hidden=false){ } /** - * Print info to a log file + * Print info to debug log file * * @author Andreas Gohr * @deprecated 2020-08-13 @@ -430,18 +430,10 @@ function dbg($msg,$hidden=false){ * @param string $header */ function dbglog($msg,$header=''){ - global $conf; dbg_deprecated('\\dokuwiki\\Logger'); - // The debug log isn't automatically cleaned thus only write it when - // debugging has been enabled by the user. - if($conf['allowdebug'] !== 1) return; - if(is_object($msg) || is_array($msg)){ - $msg = print_r($msg,true); - } - // was the msg as single line string? use it as header - if($header === '' && strpos($msg, "\n") === false) { + if($header === '' && is_string($msg) && strpos($msg, "\n") === false) { $header = $msg; $msg = ''; } diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php index fb8186cd8..c0f459a3c 100644 --- a/lib/plugins/config/lang/en/lang.php +++ b/lib/plugins/config/lang/en/lang.php @@ -147,6 +147,7 @@ $lang['mailfrom'] = 'Sender email address to use for automatic mails'; $lang['mailreturnpath'] = 'Recipient email address for non delivery notifications'; $lang['mailprefix'] = 'Email subject prefix to use for automatic mails. Leave blank to use the wiki title'; $lang['htmlmail'] = 'Send better looking, but larger in size HTML multipart emails. Disable for plain text only mails.'; +$lang['dontlog'] = 'Disable logging for these types of logs.'; /* Syndication Settings */ $lang['sitemap'] = 'Generate Google sitemap this often (in days). 0 to disable'; diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php index 6fdd64d6e..aa5137c2e 100644 --- a/lib/plugins/config/settings/config.metadata.php +++ b/lib/plugins/config/settings/config.metadata.php @@ -199,6 +199,14 @@ $meta['mailfrom'] = array('email', '_placeholders' => true); $meta['mailreturnpath'] = array('email', '_placeholders' => true); $meta['mailprefix'] = array('string'); $meta['htmlmail'] = array('onoff'); +$meta['dontlog'] = array( + 'disableactions', + '_choices' => array( + 'error', + 'debug', + 'deprecated', + ), +); $meta['_syndication'] = array('fieldset'); $meta['sitemap'] = array('numeric'); diff --git a/lib/plugins/logviewer/lang/en/intro.txt b/lib/plugins/logviewer/lang/en/intro.txt index f3b488ec4..5b63b148a 100644 --- a/lib/plugins/logviewer/lang/en/intro.txt +++ b/lib/plugins/logviewer/lang/en/intro.txt @@ -1,8 +1,8 @@ ====== View Logs ====== This interface allows you to view the various logs that are written by DokuWiki. By default, there shouldn't be logged -much here (it depends on your log settings). However if something goes wrong, chances are high, you'll find useful info -here. All times are UTC! +much here (it depends on your [[doku>config:dontlog|log settings]]). However if something goes wrong, chances are high, +you'll find useful info here. All times are UTC! Please be aware **log files can contain sensitive information** like passwords, paths or other secrets. Be sure to redact the logs appropriately when posting them on the forum or in bug reports! From 6071f0eef30466192d0db9320b73a17c5ef7df39 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 15 Oct 2020 12:13:32 +0200 Subject: [PATCH 7/7] added JavaScript based filter mechanism --- lib/plugins/logviewer/admin.php | 2 +- lib/plugins/logviewer/lang/en/lang.php | 3 ++- lib/plugins/logviewer/script.js | 21 +++++++++++++++++++-- lib/plugins/logviewer/style.less | 10 ++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/plugins/logviewer/admin.php b/lib/plugins/logviewer/admin.php index 7a28e208b..6eb177af2 100644 --- a/lib/plugins/logviewer/admin.php +++ b/lib/plugins/logviewer/admin.php @@ -59,7 +59,7 @@ class admin_plugin_logviewer extends DokuWiki_Admin_Plugin $form->setHiddenField('do', 'admin'); $form->setHiddenField('page', 'logviewer'); $form->setHiddenField('facility', $this->facility); - $form->addTextInput('date','Date*')->attr('type','date')->val($this->date)->addClass('quickselect'); + $form->addTextInput('date',$this->getLang('date'))->attr('type','date')->val($this->date)->addClass('quickselect'); $form->addButton('submit','>')->attr('type','submit'); echo $form->toHTML(); diff --git a/lib/plugins/logviewer/lang/en/lang.php b/lib/plugins/logviewer/lang/en/lang.php index 3f32e0bed..7daff6ab4 100644 --- a/lib/plugins/logviewer/lang/en/lang.php +++ b/lib/plugins/logviewer/lang/en/lang.php @@ -6,4 +6,5 @@ */ $lang['menu'] = 'View Logs'; - +$lang['date'] = 'Date'; +$lang['js']['filter'] = 'Filter Loglines:'; diff --git a/lib/plugins/logviewer/script.js b/lib/plugins/logviewer/script.js index 5a5303c84..ebb9478b5 100644 --- a/lib/plugins/logviewer/script.js +++ b/lib/plugins/logviewer/script.js @@ -3,6 +3,23 @@ */ jQuery(function () { var $dl = jQuery('#plugin__logviewer').find('dl'); - if(!$dl.length) return; - $dl.animate({ scrollTop: $dl.prop("scrollHeight")}, 500); + if (!$dl.length) return; + $dl.animate({scrollTop: $dl.prop("scrollHeight")}, 500); + + + var $filter = jQuery(''); + $filter.on('keyup', function (e) { + var re = new RegExp($filter.val(), 'i'); + + $dl.find('dt').each(function (idx, elem) { + if (elem.innerText.match(re)) { + jQuery(elem).removeClass('hidden'); + } else { + jQuery(elem).addClass('hidden'); + } + }); + }); + $dl.before($filter); + $filter.wrap(''); + $filter.before(LANG.plugins.logviewer.filter + ' '); }); diff --git a/lib/plugins/logviewer/style.less b/lib/plugins/logviewer/style.less index f9c8b1d89..af78379c0 100644 --- a/lib/plugins/logviewer/style.less +++ b/lib/plugins/logviewer/style.less @@ -7,6 +7,12 @@ margin-bottom: 2em; } + label { + display: block; + margin-top: -1em; + margin-bottom: 1em; + } + dl { max-height: 80vh; overflow: auto; @@ -14,6 +20,10 @@ dt { display: flex; + &.hidden { + display: none; + } + .datetime { flex: 0 0 auto; margin-right: 1em;