xref: /dokuwiki/inc/Logger.php (revision cad4fbf6e21bd4a053f1f42b9e40c74f1cfaeab6)
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
17*cad4fbf6SAndreas Gohr    protected $isLogging = true;
18*cad4fbf6SAndreas 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    {
26*cad4fbf6SAndreas Gohr        global $conf;
270ecde6ceSAndreas Gohr        $this->facility = $facility;
28*cad4fbf6SAndreas Gohr
29*cad4fbf6SAndreas Gohr        // Should logging be disabled for this facility?
30*cad4fbf6SAndreas Gohr        $dontlog = explode(',', $conf['dontlog']);
31*cad4fbf6SAndreas Gohr        $dontlog = array_map('trim', $dontlog);
32*cad4fbf6SAndreas 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    {
430ecde6ceSAndreas Gohr        if (self::$instances[$facility] === null) {
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
56*cad4fbf6SAndreas 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
72*cad4fbf6SAndreas 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
88*cad4fbf6SAndreas 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
104*cad4fbf6SAndreas Gohr     * @return bool has a log been written?
1050ecde6ceSAndreas Gohr     */
1060ecde6ceSAndreas Gohr    public function log($message, $details = null, $file = '', $line = 0)
1070ecde6ceSAndreas Gohr    {
108*cad4fbf6SAndreas Gohr        if(!$this->isLogging) return false;
109*cad4fbf6SAndreas 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