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)
This commit is contained in:
parent
51c1fbb36b
commit
0ecde6ce23
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 <<<EOT
|
||||
|
@ -64,7 +64,7 @@ EOT;
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Logger constructor.
|
||||
*
|
||||
* @param string $facility The type of log
|
||||
*/
|
||||
protected function __construct($facility)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
|
@ -424,14 +424,13 @@ function dbg($msg,$hidden=false){
|
|||
* Print info to a 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.
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
23
inc/init.php
23
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];
|
||||
|
|
Loading…
Reference in New Issue