Skip to content
Extraits de code Groupes Projets
Log.php 21,3 ko
Newer Older
  • Learn to ignore specific revisions
  • <?php
    /**
     * Piwik - Open source web analytics
    
    robocoder's avatar
    robocoder a validé
     * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
    
    robocoder's avatar
    robocoder a validé
     * @category Piwik
     * @package Piwik
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
    use Piwik\Db;
    
    
     * Logging utility class.
     * 
     * Log entries are made with a message and log level. The logging utility will tag each
     * log entry with the name of the plugin that's doing the logging. If no plugin is found,
     * the name of the current class is used.
     * 
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
     * You can log messages using one of the public static functions (eg, 'error', 'warning',
    
     * 'info', etc.). Messages logged with the **error** level will **always** be logged to
     * the screen, regardless of whether the [log] log_writer config option includes the
     * screen writer.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
     * Currently, Piwik supports the following logging backends:
    
     * 
     * - **screen**: logging to the screen
     * - **file**: logging to a file
     * - **database**: logging to Piwik's MySQL database
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
     * The logging utility can be configured by manipulating the INI config options in the
    
     * 
     * The following configuration options can be set:
     * 
     * - `log_writers[]`: This is an array of log writer IDs. The three log writers provided
     *                    by Piwik core are **file**, **screen** and **database**. You can
     *                    get more by installing plugins. The default value is **screen**.
     * - `log_level`: The current log level. Can be **ERROR**, **WARN**, **INFO**, **DEBUG**,
     *                or **VERBOSE**. Log entries made with a log level that is as or more
     *                severe than the current log level will be outputted. Others will be
     *                ignored. The default level is **WARN**.
     * - `log_only_when_cli`: 0 or 1. If 1, logging is only enabled when Piwik is executed
     *                        in the command line (for example, by the archive.php cron
     *                        script). Default: 0.
     * - `log_only_when_debug_parameter`: 0 or 1. If 1, logging is only enabled when the
     *                                    `debug` query parameter is 1. Default: 0.
     * - `logger_file_path`: For the file log writer, specifies the path to the log file
     *                       to log to or a path to a directory to store logs in. If a
     *                       directory, the file name is piwik.log. Can be relative to
     *                       Piwik's root dir or an absolute path. Defaults to **tmp/logs**.
     * 
     * ### Custom message formatting
     * 
     * If you'd like to format log messages differently for different backends, you can use
    
     * one of the `'Log.format...Message'` events.
     * 
     * These events are fired when an object is logged. You can create your own custom class
     * containing the information to log and listen to these events to format it correctly for
     * different backends.
     * 
     * If you don't care about the backend when formatting an object, implement a `__toString()`
     * in the custom class.
    
     * New logging backends can be added via the {@hook Log.getAvailableWriters}` event. A log
    
     * writer is just a callback that accepts log entry information (such as the message,
     * level, etc.), so any backend could conceivably be used (including existing PSR3
     * backends).
     * 
     * ### Examples
     * 
     * **Basic logging**
     * 
     *     Log::error("This log message will end up on the screen and in a file.")
     *     Log::verbose("This log message uses %s params, but %s will only be called if the"
     *                . " configured log level includes %s.", "sprintf", "sprintf", "verbose");
     * 
    
     * **Logging objects**
     * 
     *     class MyDebugInfo
     *     {
     *         // ...
     * 
     *         public function __toString()
     *         {
     *             return // ...
     *         }
     *     }
     * 
     *     try {
     *         $myThirdPartyServiceClient->doSomething();
     *     } catch (Exception $unexpectedError) {
     *         $debugInfo = new MyDebugInfo($unexpectedError, $myThirdPartyServiceClient);
     *         Log::debug($debugInfo);
     *     }
     * 
    
    sgiehl's avatar
    sgiehl a validé
     * @method static \Piwik\Log getInstance()
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        // log levels
        const NONE = 0;
        const ERROR = 1;
        const WARN = 2;
        const INFO = 3;
        const DEBUG = 4;
        const VERBOSE = 5;
    
        // config option names
        const LOG_LEVEL_CONFIG_OPTION = 'log_level';
        const LOG_WRITERS_CONFIG_OPTION = 'log_writers';
        const LOGGER_FILE_PATH_CONFIG_OPTION = 'logger_file_path';
    
        const STRING_MESSAGE_FORMAT_OPTION = 'string_message_format';
    
        const FORMAT_FILE_MESSAGE_EVENT = 'Log.formatFileMessage';
    
        const FORMAT_SCREEN_MESSAGE_EVENT = 'Log.formatScreenMessage';
    
        const FORMAT_DATABASE_MESSAGE_EVENT = 'Log.formatDatabaseMessage';
    
    
        const GET_AVAILABLE_WRITERS_EVENT = 'Log.getAvailableWriters';
    
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        /**
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * The current logging level. Everything of equal or greater priority will be logged.
         * Everything else will be ignored.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @var int
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        private $currentLogLevel = self::WARN;
    
        /**
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * The array of callbacks executed when logging to a file. Each callback writes a log
         * message to a logging backend.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @var array
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        private $writers = array();
    
        /**
    
         * The log message format string that turns a tag name, date-time and message into
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * one string to log.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @var string
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
    
    diosmosis's avatar
    diosmosis a validé
        private $logMessageFormat = "%level% %tag%[%datetime%] %message%";
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * If we're logging to a file, this is the path to the file to log to.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @var string
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private $logToFilePath;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        /**
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * True if we're currently setup to log to a screen, false if otherwise.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @var bool
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        private $loggingToScreen;
    
    
    sgiehl's avatar
    sgiehl a validé
        /**
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * Constructor.
    
    sgiehl's avatar
    sgiehl a validé
         */
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            $logConfig = Config::getInstance()->log;
            $this->setCurrentLogLevelFromConfig($logConfig);
            $this->setLogWritersFromConfig($logConfig);
            $this->setLogFilePathFromConfig($logConfig);
    
            $this->setStringLogMessageFormat($logConfig);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            $this->disableLoggingBasedOnConfig($logConfig);
        }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        /**
         * Logs a message using the ERROR log level.
    
         * _Note: Messages logged with the ERROR level are always logged to the screen in addition
         * to configured writers._
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $message The log message. This can be a sprintf format string.
         * @param ... mixed Optional sprintf params.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        public static function error($message /* ... */)
    
            self::logMessage(self::ERROR, $message, array_slice(func_get_args(), 1));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        /**
         * Logs a message using the WARNING log level.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $message The log message. This can be a sprintf format string.
         * @param ... mixed Optional sprintf params.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        public static function warning($message /* ... */)
        {
    
            self::logMessage(self::WARN, $message, array_slice(func_get_args(), 1));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        /**
         * Logs a message using the INFO log level.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $message The log message. This can be a sprintf format string.
         * @param ... mixed Optional sprintf params.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        public static function info($message /* ... */)
        {
    
            self::logMessage(self::INFO, $message, array_slice(func_get_args(), 1));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        /**
         * Logs a message using the DEBUG log level.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $message The log message. This can be a sprintf format string.
         * @param ... mixed Optional sprintf params.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        public static function debug($message /* ... */)
        {
    
            self::logMessage(self::DEBUG, $message, array_slice(func_get_args(), 1));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        /**
         * Logs a message using the VERBOSE log level.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $message The log message. This can be a sprintf format string.
         * @param ... mixed Optional sprintf params.
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         */
        public static function verbose($message /* ... */)
        {
    
            self::logMessage(self::VERBOSE, $message, array_slice(func_get_args(), 1));
    
         * Creates log message combining logging info including a log level, tag name,
    
         * date time, and caller-provided log message. The log message can be set through
         * the `[log] string_message_format` INI config option. By default it will
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * create log messages like:
    
         * **LEVEL [tag:datetime] log message**
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param int $level
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
         * @param string $datetime
         * @param string $message
         * @return string
         */
    
        public function formatMessage($level, $tag, $datetime, $message)
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        {
            return str_replace(
    
                array("%tag%", "%message%", "%datetime%", "%level%"),
                array($tag, $message, $datetime, $this->getStringLevel($level)),
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                $this->logMessageFormat
            );
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function setLogWritersFromConfig($logConfig)
        {
    
            $availableWritersByName = $this->getAvailableWriters();
    
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            // set the log writers
            $logWriters = $logConfig[self::LOG_WRITERS_CONFIG_OPTION];
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            $logWriters = array_map('trim', $logWriters);
            foreach ($logWriters as $writerName) {
    
                if (empty($availableWritersByName[$writerName])) {
                    continue;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
    
    
                $this->writers[] = $availableWritersByName[$writerName];
    
    
                if ($writerName == 'screen') {
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                    $this->loggingToScreen = true;
                }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        private function setCurrentLogLevelFromConfig($logConfig)
        {
            if (!empty($logConfig[self::LOG_LEVEL_CONFIG_OPTION])) {
    
                $logLevel = $this->getLogLevelFromStringName($logConfig[self::LOG_LEVEL_CONFIG_OPTION]);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                if ($logLevel >= self::NONE // sanity check
                    && $logLevel <= self::VERBOSE
                ) {
                    $this->currentLogLevel = $logLevel;
                }
            }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function setStringLogMessageFormat($logConfig)
        {
            if (isset($logConfig['string_message_format'])) {
                $this->logMessageFormat = $logConfig['string_message_format'];
            }
        }
    
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function setLogFilePathFromConfig($logConfig)
    
            $logPath = $logConfig[self::LOGGER_FILE_PATH_CONFIG_OPTION];
    
            if (!SettingsServer::isWindows()
                && $logPath[0] != '/'
            ) {
    
                $logPath = PIWIK_USER_PATH . DIRECTORY_SEPARATOR . $logPath;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            }
    
            $logPath = SettingsPiwik::rewriteTmpPathWithHostname($logPath);
    
            if (is_dir($logPath)) {
                $logPath .= '/piwik.log';
            }
    
            $this->logToFilePath = $logPath;
    
        private function getAvailableWriters()
    
            $writers = array();
    
    
            /**
             * This event is called when the Log instance is created. Plugins can use this event to
             * make new logging writers available.
             *
    
             * A logging writer is a callback with the following signature:
             * 
             *     function (int $level, string $tag, string $datetime, string $message)
    
             * `$level` is the log level to use, `$tag` is the log tag used, `$datetime` is the date time
             * of the logging call and `$message` is the formatted log message.
    
             * Logging writers must be associated by name in the array passed to event handlers. The
             * name specified can be used in Piwik's INI configuration.
    
             *     public function getAvailableWriters(&$writers) {
    
             *         $writers['myloggername'] = function ($level, $tag, $datetime, $message) {
             *             // ...
             *         };
    
             *     // 'myloggername' can now be used in the log_writers config option.
             * 
    
             * @param array $writers Array mapping writer names with logging writers.
    
            Piwik::postEvent(self::GET_AVAILABLE_WRITERS_EVENT, array(&$writers));
    
    
            $writers['file'] = array($this, 'logToFile');
            $writers['screen'] = array($this, 'logToScreen');
            $writers['database'] = array($this, 'logToDatabase');
            return $writers;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        private function logToFile($level, $tag, $datetime, $message)
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        {
    
            if (is_string($message)) {
    
                $message = $this->formatMessage($level, $tag, $datetime, $message);
    
            } else {
    
                 * Triggered when trying to log an object to a file. Plugins can use
    
                 * this event to convert objects to strings before they are logged.
                 *
    
                 * **Example**
                 * 
                 *     public function formatFileMessage(&$message, $level, $tag, $datetime, $logger) {
                 *         if ($message instanceof MyCustomDebugInfo) {
                 *             $message = $message->formatForFile();
                 *         }
                 *     }
                 * 
    
                 * @param mixed &$message The object that is being logged. Event handlers should
                 *                        check if the object is of a certain type and if it is,
    
                 *                        set `$message` to the string that should be logged.
    
                 * @param int $level The log level used with this log entry.
                 * @param string $tag The current plugin that started logging (or if no plugin,
                 *                    the current class).
                 * @param string $datetime Datetime of the logging call.
                 * @param Log $logger The Log singleton.
    
                Piwik::postEvent(self::FORMAT_FILE_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            }
    
            if (empty($message)) {
                return;
    
            if(!file_put_contents($this->logToFilePath, $message . "\n", FILE_APPEND)) {
                $message = Filechecks::getErrorMessageMissingPermissions($this->logToFilePath);
                throw new \Exception( $message );
            }
    
        private function logToScreen($level, $tag, $datetime, $message)
    
            static $currentRequestKey;
    
            if (empty($currentRequestKey)) {
    
                $currentRequestKey = substr(Common::generateUniqId(), 0, 5);
            }
    
    
            if (is_string($message)) {
    
                if (!defined('PIWIK_TEST_MODE')
                    || !PIWIK_TEST_MODE
                ) {
    
                    $message = '[' . $currentRequestKey . '] ' . $message;
                }
    
                $message = $this->formatMessage($level, $tag, $datetime, $message);
    
    
                if (!Common::isPhpCliMode()) {
    
                    $message = Common::sanitizeInputValue($message);
                    $message = '<pre>' . $message . '</pre>';
                }
    
    
            } else {
    
                 * Triggered when trying to log an object to the screen. Plugins can use
    
                 * this event to convert objects to strings before they are logged.
                 *
                 * The result of this callback can be HTML so no sanitization is done on the result.
    
                 * This means **YOU MUST SANITIZE THE MESSAGE YOURSELF** if you use this event.
    
                 * **Example**
                 * 
                 *     public function formatScreenMessage(&$message, $level, $tag, $datetime, $logger) {
                 *         if ($message instanceof MyCustomDebugInfo) {
                 *             $message = Common::sanitizeInputValue($message->formatForScreen());
                 *         }
                 *     }
                 * 
    
                 * @param mixed &$message The object that is being logged. Event handlers should
                 *                        check if the object is of a certain type and if it is,
    
                 *                        set `$message` to the string that should be logged.
    
                 * @param int $level The log level used with this log entry.
                 * @param string $tag The current plugin that started logging (or if no plugin,
                 *                    the current class).
                 * @param string $datetime Datetime of the logging call.
                 * @param Log $logger The Log singleton.
    
                Piwik::postEvent(self::FORMAT_SCREEN_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            }
    
            if (empty($message)) {
                return;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            echo $message . "\n";
    
        private function logToDatabase($level, $tag, $datetime, $message)
    
            if (is_string($message)) {
    
                $message = $this->formatMessage($level, $tag, $datetime, $message);
    
            } else {
    
                 * Triggered when trying to log an object to a database table. Plugins can use
    
                 * this event to convert objects to strings before they are logged.
                 *
    
                 * **Example**
                 * 
                 *     public function formatDatabaseMessage(&$message, $level, $tag, $datetime, $logger) {
                 *         if ($message instanceof MyCustomDebugInfo) {
                 *             $message = $message->formatForDatabase();
                 *         }
                 *     }
                 * 
    
                 * @param mixed &$message The object that is being logged. Event handlers should
                 *                        check if the object is of a certain type and if it is,
    
                 *                        set `$message` to the string that should be logged.
    
                 * @param int $level The log level used with this log entry.
                 * @param string $tag The current plugin that started logging (or if no plugin,
                 *                    the current class).
                 * @param string $datetime Datetime of the logging call.
                 * @param Log $logger The Log singleton.
    
                Piwik::postEvent(self::FORMAT_DATABASE_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            }
    
            if (empty($message)) {
                return;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            $sql = "INSERT INTO " . Common::prefixTable('logger_message')
    
                . " (tag, timestamp, level, message)"
                . " VALUES (?, ?, ?, ?)";
    
            Db::query($sql, array($tag, $datetime, self::getStringLevel($level), (string)$message));
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function doLog($level, $message, $sprintfParams = array())
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            if ($this->shouldLoggerLog($level)) {
                $datetime = date("Y-m-d H:i:s");
    
                if (is_string($message)
                    && !empty($sprintfParams)
                ) {
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                    $message = vsprintf($message, $sprintfParams);
                }
    
    
                if (version_compare(phpversion(), '5.3.6', '>=')) {
                    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
                } else {
                    $backtrace = debug_backtrace();
                }
    
                $tag = Plugin::getPluginNameFromBacktrace($backtrace);
    
                // if we can't determine the plugin, use the name of the calling class
                if ($tag == false) {
                    $tag = $this->getClassNameThatIsLogging($backtrace);
                }
    
                $this->writeMessage($level, $tag, $datetime, $message);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        private function writeMessage($level, $tag, $datetime, $message)
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        {
            foreach ($this->writers as $writer) {
    
                call_user_func($writer, $level, $tag, $datetime, $message);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
    
            // errors are always printed to screen
            if ($level == self::ERROR
                && !$this->loggingToScreen
            ) {
    
                $this->logToScreen($level, $tag, $datetime, $message);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
        private static function logMessage($level, $message, $sprintfParams)
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        {
    
            self::getInstance()->doLog($level, $message, $sprintfParams);
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function shouldLoggerLog($level)
        {
            return $level <= $this->currentLogLevel;
        }
    
        private function disableLoggingBasedOnConfig($logConfig)
        {
            $disableLogging = false;
    
            if (!empty($logConfig['log_only_when_cli'])
                && !Common::isPhpCliMode()
            ) {
                $disableLogging = true;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            if (!empty($logConfig['log_only_when_debug_parameter'])
                && !isset($_REQUEST['debug'])
            ) {
                $disableLogging = true;
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
            if ($disableLogging) {
                $this->currentLogLevel = self::NONE;
            }
        }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
        private function getLogLevelFromStringName($name)
        {
    
            $name = strtoupper($name);
            switch ($name) {
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                case 'NONE':
                    return self::NONE;
                case 'ERROR':
                    return self::ERROR;
                case 'WARN':
                    return self::WARN;
                case 'INFO':
                    return self::INFO;
                case 'DEBUG':
                    return self::DEBUG;
                case 'VERBOSE':
                    return self::VERBOSE;
                default:
                    return -1;
            }
        }
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
    
        private function getStringLevel($level)
        {
            static $levelToName = array(
    
                self::NONE    => 'NONE',
                self::ERROR   => 'ERROR',
                self::WARN    => 'WARN',
                self::INFO    => 'INFO',
                self::DEBUG   => 'DEBUG',
    
    Benaka Moorthi's avatar
    Benaka Moorthi a validé
                self::VERBOSE => 'VERBOSE'
            );
            return $levelToName[$level];
        }
    
    
        private function getClassNameThatIsLogging($backtrace)
        {
            foreach ($backtrace as $tracepoint) {
                if (isset($tracepoint['class'])
                    && $tracepoint['class'] != "Piwik\\Log"
    
                    && $tracepoint['class'] != "Piwik\\Piwik"
    
                    && $tracepoint['class'] != "Piwik\\CronArchive"