10ecde6ceSAndreas Gohr<?php 20ecde6ceSAndreas Gohr 30ecde6ceSAndreas Gohrnamespace dokuwiki; 40ecde6ceSAndreas Gohr 50ecde6ceSAndreas Gohrclass Logger 60ecde6ceSAndreas Gohr{ 70ecde6ceSAndreas Gohr const LOG_ERROR = 'error'; 80ecde6ceSAndreas Gohr const LOG_DEPRECATED = 'deprecated'; 90ecde6ceSAndreas Gohr const LOG_DEBUG = 'debug'; 100ecde6ceSAndreas Gohr 110ecde6ceSAndreas Gohr /** @var Logger[] */ 120ecde6ceSAndreas Gohr static protected $instances; 130ecde6ceSAndreas Gohr 140ecde6ceSAndreas Gohr /** @var string what kind of log is this */ 150ecde6ceSAndreas Gohr protected $facility; 160ecde6ceSAndreas Gohr 17cad4fbf6SAndreas Gohr protected $isLogging = true; 18cad4fbf6SAndreas Gohr 190ecde6ceSAndreas Gohr /** 200ecde6ceSAndreas Gohr * Logger constructor. 210ecde6ceSAndreas Gohr * 220ecde6ceSAndreas Gohr * @param string $facility The type of log 230ecde6ceSAndreas Gohr */ 240ecde6ceSAndreas Gohr protected function __construct($facility) 250ecde6ceSAndreas Gohr { 26cad4fbf6SAndreas Gohr global $conf; 270ecde6ceSAndreas Gohr $this->facility = $facility; 28cad4fbf6SAndreas Gohr 29cad4fbf6SAndreas Gohr // Should logging be disabled for this facility? 30cad4fbf6SAndreas Gohr $dontlog = explode(',', $conf['dontlog']); 31cad4fbf6SAndreas Gohr $dontlog = array_map('trim', $dontlog); 32cad4fbf6SAndreas Gohr if (in_array($facility, $dontlog)) $this->isLogging = false; 330ecde6ceSAndreas Gohr } 340ecde6ceSAndreas Gohr 350ecde6ceSAndreas Gohr /** 360ecde6ceSAndreas Gohr * Return a Logger instance for the given facility 370ecde6ceSAndreas Gohr * 380ecde6ceSAndreas Gohr * @param string $facility The type of log 390ecde6ceSAndreas Gohr * @return Logger 400ecde6ceSAndreas Gohr */ 410ecde6ceSAndreas Gohr static public function getInstance($facility = self::LOG_ERROR) 420ecde6ceSAndreas Gohr { 43*a8f9f939SDamien Regad if (empty(self::$instances[$facility])) { 440ecde6ceSAndreas Gohr self::$instances[$facility] = new Logger($facility); 450ecde6ceSAndreas Gohr } 460ecde6ceSAndreas Gohr return self::$instances[$facility]; 470ecde6ceSAndreas Gohr } 480ecde6ceSAndreas Gohr 490ecde6ceSAndreas Gohr /** 50c2050393SAndreas Gohr * Convenience method to directly log to the error log 51c2050393SAndreas Gohr * 52c2050393SAndreas Gohr * @param string $message The log message 53c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 54c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 55c2050393SAndreas Gohr * @param int $line A line number for the above file 56cad4fbf6SAndreas Gohr * @return bool has a log been written? 57c2050393SAndreas Gohr */ 58c2050393SAndreas Gohr static public function error($message, $details = null, $file = '', $line = 0) 59c2050393SAndreas Gohr { 60c2050393SAndreas Gohr return self::getInstance(self::LOG_ERROR)->log( 61c2050393SAndreas Gohr $message, $details, $file, $line 62c2050393SAndreas Gohr ); 63c2050393SAndreas Gohr } 64c2050393SAndreas Gohr 65c2050393SAndreas Gohr /** 66c2050393SAndreas Gohr * Convenience method to directly log to the debug log 67c2050393SAndreas Gohr * 68c2050393SAndreas Gohr * @param string $message The log message 69c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 70c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 71c2050393SAndreas Gohr * @param int $line A line number for the above file 72cad4fbf6SAndreas Gohr * @return bool has a log been written? 73c2050393SAndreas Gohr */ 74c2050393SAndreas Gohr static public function debug($message, $details = null, $file = '', $line = 0) 75c2050393SAndreas Gohr { 76c2050393SAndreas Gohr return self::getInstance(self::LOG_DEBUG)->log( 77c2050393SAndreas Gohr $message, $details, $file, $line 78c2050393SAndreas Gohr ); 79c2050393SAndreas Gohr } 80c2050393SAndreas Gohr 81c2050393SAndreas Gohr /** 82c2050393SAndreas Gohr * Convenience method to directly log to the deprecation log 83c2050393SAndreas Gohr * 84c2050393SAndreas Gohr * @param string $message The log message 85c2050393SAndreas Gohr * @param mixed $details Any details that should be added to the log entry 86c2050393SAndreas Gohr * @param string $file A source filename if this is related to a source position 87c2050393SAndreas Gohr * @param int $line A line number for the above file 88cad4fbf6SAndreas Gohr * @return bool has a log been written? 89c2050393SAndreas Gohr */ 90c2050393SAndreas Gohr static public function deprecated($message, $details = null, $file = '', $line = 0) 91c2050393SAndreas Gohr { 92c2050393SAndreas Gohr return self::getInstance(self::LOG_DEPRECATED)->log( 93c2050393SAndreas Gohr $message, $details, $file, $line 94c2050393SAndreas Gohr ); 95c2050393SAndreas Gohr } 96c2050393SAndreas Gohr 97c2050393SAndreas Gohr /** 980ecde6ceSAndreas Gohr * Log a message to the facility log 990ecde6ceSAndreas Gohr * 1000ecde6ceSAndreas Gohr * @param string $message The log message 1010ecde6ceSAndreas Gohr * @param mixed $details Any details that should be added to the log entry 1020ecde6ceSAndreas Gohr * @param string $file A source filename if this is related to a source position 1030ecde6ceSAndreas Gohr * @param int $line A line number for the above file 104cad4fbf6SAndreas Gohr * @return bool has a log been written? 1050ecde6ceSAndreas Gohr */ 1060ecde6ceSAndreas Gohr public function log($message, $details = null, $file = '', $line = 0) 1070ecde6ceSAndreas Gohr { 108cad4fbf6SAndreas Gohr if(!$this->isLogging) return false; 109cad4fbf6SAndreas Gohr 1100ecde6ceSAndreas Gohr // details are logged indented 11170cc2cbfSAndreas Gohr if ($details) { 11270cc2cbfSAndreas Gohr if (!is_string($details)) { 1130ecde6ceSAndreas Gohr $details = json_encode($details, JSON_PRETTY_PRINT); 11470cc2cbfSAndreas Gohr } 1150ecde6ceSAndreas Gohr $details = explode("\n", $details); 1160ecde6ceSAndreas Gohr $loglines = array_map(function ($line) { 1170ecde6ceSAndreas Gohr return ' ' . $line; 1180ecde6ceSAndreas Gohr }, $details); 1190ecde6ceSAndreas Gohr } elseif ($details) { 1200ecde6ceSAndreas Gohr $loglines = [$details]; 1210ecde6ceSAndreas Gohr } else { 1220ecde6ceSAndreas Gohr $loglines = []; 1230ecde6ceSAndreas Gohr } 1240ecde6ceSAndreas Gohr 12570cc2cbfSAndreas Gohr // datetime, fileline, message 12670cc2cbfSAndreas Gohr $logline = gmdate('Y-m-d H:i:s') . "\t"; 1270ecde6ceSAndreas Gohr if ($file) { 12870cc2cbfSAndreas Gohr $logline .= $file; 1290ecde6ceSAndreas Gohr if ($line) $logline .= "($line)"; 1300ecde6ceSAndreas Gohr } 13170cc2cbfSAndreas Gohr $logline .= "\t" . $message; 1320ecde6ceSAndreas Gohr 1330ecde6ceSAndreas Gohr array_unshift($loglines, $logline); 1340ecde6ceSAndreas Gohr return $this->writeLogLines($loglines); 1350ecde6ceSAndreas Gohr } 1360ecde6ceSAndreas Gohr 1370ecde6ceSAndreas Gohr /** 13870cc2cbfSAndreas Gohr * Construct the log file for the given day 13970cc2cbfSAndreas Gohr * 14070cc2cbfSAndreas Gohr * @param false|string|int $date Date to access, false for today 14170cc2cbfSAndreas Gohr * @return string 14270cc2cbfSAndreas Gohr */ 14370cc2cbfSAndreas Gohr public function getLogfile($date = false) 14470cc2cbfSAndreas Gohr { 14570cc2cbfSAndreas Gohr global $conf; 14670cc2cbfSAndreas Gohr 14770cc2cbfSAndreas Gohr if ($date !== null) $date = strtotime($date); 14870cc2cbfSAndreas Gohr if (!$date) $date = time(); 14970cc2cbfSAndreas Gohr 15070cc2cbfSAndreas Gohr return $conf['logdir'] . '/' . $this->facility . '/' . date('Y-m-d', $date) . '.log'; 15170cc2cbfSAndreas Gohr } 15270cc2cbfSAndreas Gohr 15370cc2cbfSAndreas Gohr /** 1540ecde6ceSAndreas Gohr * Write the given lines to today's facility log 1550ecde6ceSAndreas Gohr * 1560ecde6ceSAndreas Gohr * @param string[] $lines the raw lines to append to the log 1570ecde6ceSAndreas Gohr * @return bool true if the log was written 1580ecde6ceSAndreas Gohr */ 1590ecde6ceSAndreas Gohr protected function writeLogLines($lines) 1600ecde6ceSAndreas Gohr { 16170cc2cbfSAndreas Gohr $logfile = $this->getLogfile(); 1620ecde6ceSAndreas Gohr return io_saveFile($logfile, join("\n", $lines) . "\n", true); 1630ecde6ceSAndreas Gohr } 1640ecde6ceSAndreas Gohr} 165