Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

central logging mechanism #3230

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions conf/dokuwiki.php
Expand Up @@ -111,6 +111,7 @@
$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.
Expand Down
1 change: 1 addition & 0 deletions data/log/_dummy
@@ -0,0 +1 @@
You can safely delete this file.
3 changes: 2 additions & 1 deletion inc/Debug/DebugHelper.php
Expand Up @@ -5,6 +5,7 @@

use Doku_Event;
use dokuwiki\Extension\EventHandler;
use dokuwiki\Logger;

class DebugHelper
{
Expand Down Expand Up @@ -160,7 +161,7 @@ private static function triggerDeprecationEvent(
if ($event->data['alternative']) {
$msg .= ' ' . $event->data['alternative'] . ' should be used instead!';
}
dbglog($msg);
Logger::getInstance(Logger::LOG_DEPRECATED)->log($msg);
}
$event->advise_after();
}
Expand Down
20 changes: 8 additions & 12 deletions inc/ErrorHandler.php
Expand Up @@ -36,7 +36,7 @@ public static function fatalException($e)
$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 <<<EOT
Expand Down Expand Up @@ -64,7 +64,7 @@ public static function fatalException($e)
public static function showExceptionMsg($e, $intro = 'Error!')
{
$msg = hsc($intro) . '<br />' . hsc(get_class($e) . ': ' . $e->getMessage());
if (self::logException($e)) $msg .= '<br />More info is available in the _error.log';
if (self::logException($e)) $msg .= '<br />More info is available in the error log.';
msg($msg, -1);
}

Expand Down Expand Up @@ -100,16 +100,12 @@ public static function fatalShutdown()
*/
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()
);
}

/**
Expand Down
8 changes: 6 additions & 2 deletions inc/Extension/Event.php
Expand Up @@ -3,6 +3,8 @@

namespace dokuwiki\Extension;

use dokuwiki\Logger;

/**
* The Action plugin event
*/
Expand Down Expand Up @@ -71,7 +73,8 @@ public function advise_before($enablePreventDefault = true)
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);
Expand All @@ -92,7 +95,8 @@ public function advise_after()
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');
}
}

Expand Down
164 changes: 164 additions & 0 deletions inc/Logger.php
@@ -0,0 +1,164 @@
<?php

namespace dokuwiki;

class Logger
{
const LOG_ERROR = 'error';
const LOG_DEPRECATED = 'deprecated';
const LOG_DEBUG = 'debug';

/** @var Logger[] */
static protected $instances;

/** @var string what kind of log is this */
protected $facility;

protected $isLogging = true;

/**
* Logger constructor.
*
* @param string $facility The type of log
*/
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;
}

/**
* 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];
}

/**
* 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 has a log been written?
*/
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 has a log been written?
*/
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 has a log been written?
*/
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
*
* @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 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)) {
$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 = [];
}

// datetime, fileline, message
$logline = gmdate('Y-m-d H:i:s') . "\t";
if ($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
*
* @param string[] $lines the raw lines to append to the log
* @return bool true if the log was written
*/
protected function writeLogLines($lines)
{
$logfile = $this->getLogfile();
return io_saveFile($logfile, join("\n", $lines) . "\n", true);
}
}
14 changes: 8 additions & 6 deletions inc/Sitemap/Mapper.php
Expand Up @@ -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.
Expand Down Expand Up @@ -43,14 +44,14 @@ public static function generate(){

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
Expand Down Expand Up @@ -150,10 +151,11 @@ public static function pingSearchEngines() {
$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();
Expand Down
2 changes: 1 addition & 1 deletion inc/Ui/Admin.php
Expand Up @@ -12,7 +12,7 @@
*/
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;
Expand Down
35 changes: 14 additions & 21 deletions inc/infoutils.php
Expand Up @@ -7,6 +7,7 @@
*/

use dokuwiki\HTTP\DokuHTTPClient;
use dokuwiki\Logger;

if(!defined('DOKU_MESSAGEURL')){
if(in_array('ssl', stream_get_transports())) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -421,33 +422,25 @@ function dbg($msg,$hidden=false){
}

/**
* Print info to a log file
* Print info to debug log file
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @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.
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 === '' && is_string($msg) && strpos($msg, "\n") === false) {
$header = $msg;
$msg = '';
}

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);
}
Logger::getInstance(Logger::LOG_DEBUG)->log(
$header, $msg
);
}

/**
Expand Down