5 use dokuwiki\Extension\Event
;
8 * Log messages to a daily log file
12 public const LOG_ERROR
= 'error';
13 public const LOG_DEPRECATED
= 'deprecated';
14 public const LOG_DEBUG
= 'debug';
17 protected static $instances;
19 /** @var string what kind of log is this */
22 protected $isLogging = true;
27 * @param string $facility The type of log
29 protected function __construct($facility)
32 $this->facility
= $facility;
34 // Should logging be disabled for this facility?
35 $dontlog = explode(',', $conf['dontlog']);
36 $dontlog = array_map('trim', $dontlog);
37 if (in_array($facility, $dontlog)) $this->isLogging
= false;
41 * Return a Logger instance for the given facility
43 * @param string $facility The type of log
46 public static function getInstance($facility = self
::LOG_ERROR
)
48 if (empty(self
::$instances[$facility])) {
49 self
::$instances[$facility] = new Logger($facility);
51 return self
::$instances[$facility];
55 * Convenience method to directly log to the error log
57 * @param string $message The log message
58 * @param mixed $details Any details that should be added to the log entry
59 * @param string $file A source filename if this is related to a source position
60 * @param int $line A line number for the above file
61 * @return bool has a log been written?
63 public static function error($message, $details = null, $file = '', $line = 0)
65 return self
::getInstance(self
::LOG_ERROR
)->log(
74 * Convenience method to directly log to the debug log
76 * @param string $message The log message
77 * @param mixed $details Any details that should be added to the log entry
78 * @param string $file A source filename if this is related to a source position
79 * @param int $line A line number for the above file
80 * @return bool has a log been written?
82 public static function debug($message, $details = null, $file = '', $line = 0)
84 return self
::getInstance(self
::LOG_DEBUG
)->log(
93 * Convenience method to directly log to the deprecation log
95 * @param string $message The log message
96 * @param mixed $details Any details that should be added to the log entry
97 * @param string $file A source filename if this is related to a source position
98 * @param int $line A line number for the above file
99 * @return bool has a log been written?
101 public static function deprecated($message, $details = null, $file = '', $line = 0)
103 return self
::getInstance(self
::LOG_DEPRECATED
)->log(
112 * Log a message to the facility log
114 * @param string $message The log message
115 * @param mixed $details Any details that should be added to the log entry
116 * @param string $file A source filename if this is related to a source position
117 * @param int $line A line number for the above file
118 * @triggers LOGGER_DATA_FORMAT can be used to change the logged data or intercept it
119 * @return bool has a log been written?
121 public function log($message, $details = null, $file = '', $line = 0)
123 global $EVENT_HANDLER;
124 if (!$this->isLogging
) return false;
128 'facility' => $this->facility
,
129 'datetime' => $datetime,
130 'message' => $message,
131 'details' => $details,
135 'logfile' => $this->getLogfile($datetime),
138 if ($EVENT_HANDLER !== null) {
139 $event = new Event('LOGGER_DATA_FORMAT', $data);
140 if ($event->advise_before()) {
141 $data['loglines'] = $this->formatLogLines($data);
143 $event->advise_after();
145 // The event system is not yet available, to ensure the log isn't lost even on
146 // fatal errors, the default action is executed
147 $data['loglines'] = $this->formatLogLines($data);
150 // only log when any data available
151 if (count($data['loglines'])) {
152 return $this->writeLogLines($data['loglines'], $data['logfile']);
159 * Is this logging instace actually logging?
163 public function isLogging()
165 return $this->isLogging
;
169 * Formats the given data as loglines
171 * @param array $data Event data from LOGGER_DATA_FORMAT
172 * @return string[] the lines to log
174 protected function formatLogLines($data)
178 // details are logged indented
180 if (!is_string($details)) {
181 $details = json_encode($details, JSON_PRETTY_PRINT
);
183 $details = explode("\n", $details);
184 $loglines = array_map(static fn($line) => ' ' . $line, $details);
185 } elseif ($details) {
186 $loglines = [$details];
191 // datetime, fileline, message
192 $logline = gmdate('Y-m-d H:i:s', $datetime) . "\t";
195 if ($line) $logline .= "($line)";
197 $logline .= "\t" . $message;
198 array_unshift($loglines, $logline);
204 * Construct the log file for the given day
206 * @param false|string|int $date Date to access, false for today
209 public function getLogfile($date = false)
213 if ($date !== null && !is_numeric($date)) {
214 $date = strtotime($date);
216 if (!$date) $date = time();
218 return $conf['logdir'] . '/' . $this->facility
. '/' . date('Y-m-d', $date) . '.log';
222 * Write the given lines to today's facility log
224 * @param string[] $lines the raw lines to append to the log
225 * @param string $logfile where to write to
226 * @return bool true if the log was written
228 protected function writeLogLines($lines, $logfile)
230 if (defined('DOKU_UNITTEST')) {
231 fwrite(STDERR
, "\n[" . $this->facility
. '] ' . implode("\n", $lines) . "\n");
233 return io_saveFile($logfile, implode("\n", $lines) . "\n", true);