View file delta_framework-main/core/lib/Core/Helpers/Log.class.php

File size: 5.9Kb
<?php
    /**
     * Copyright (c) 2022 Roman Grinko <[email protected]>
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */

    namespace Core\Helpers;

    use Core\Models\User;
    use Core\CoreException;

    class Log
    {
        /**
         * Уровни логирования
         */
        private static $priorityList = [
            LOG_DEBUG   => 'DEBUG',
            LOG_INFO    => 'INFO',
            LOG_NOTICE  => 'NOTICE',
            LOG_WARNING => 'WARNING',
            LOG_ERR     => 'ERROR',
            LOG_CRIT    => 'CRITICAL',
            LOG_ALERT   => 'ALERT',
            LOG_EMERG   => 'EMERGENCY',
        ];

        /**
         * Логирование в файл
         *
         * @param string      $message  Сообщение
         * @param string      $filename Имя файла
         * @param mixed       $content  Дополнительные параметры в виде массива, объекта, строки и т.д.
         * @param int         $priority Код состояния
         * @param string|null $system   Название системы
         * @param bool        $addEnv   Флаг необходимости указания расширенных данных
         *
         * @return int             Количество сохранённых байт
         * @throws CoreException
         */
        public static function logToFile(
            string $message,
            string $filename = 'core.log',
            $content = null,
            int $priority = LOG_DEBUG,
            string $system = null,
            bool $addEnv = true
        ): int {
            if (!USE_LOG) {
                return 1;
            }
            $jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
            $message     = str_replace(["\r\n", "\r", "\n"], PHP_EOL, trim($message));
            $logFile     = LOG_PATH . '/' . $filename;

            $logContent = '';
            if (!empty($content)) {
                if (!is_array($content) && !is_object($content)) {
                    $content = [$content];
                }
                $logContent = ' ' . json_encode($content, $jsonOptions);
                if (substr($logContent, 0, 4) == ' [{}') {
                    $logContent = ' #' . str_replace(PHP_EOL, '\n', serialize($content)) . '#';
                }
            }

            if (!array_key_exists($priority, self::$priorityList)) {
                $priority = LOG_DEBUG;
            }

            if (empty($system)) {
                $backtraceLimit = 2;
                $backtrace      = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $backtraceLimit);
                if (count($backtrace) < $backtraceLimit) {
                    $system = pathinfo($backtrace[0]['file'], PATHINFO_FILENAME);
                } else {
                    $system = $backtrace[$backtraceLimit - 1]['function'] ?: pathinfo($backtrace[$backtraceLimit - 1]['file'], PATHINFO_FILENAME);
                }
            }

            $logText    = date('[Y-m-d H:i:s] ') . $system . '.' . self::$priorityList[$priority] . ': ';
            $logTextLen = strlen($logText);
            $logText    .= str_replace(PHP_EOL, PHP_EOL . str_repeat(' ', $logTextLen), $message);

            $logTextPosEOL = strpos($logText, PHP_EOL);

            // Собираем информацию об окружении
            $logEnv = '';
            if ($addEnv) {
                $env = [
                    'ip' => SystemFunctions::getIP(),
                    'os' => SystemFunctions::getOS(),
                ];

                $userId = User::getCurrentUserId();
                if ($userId !== null) {
                    $objectUser       = new User($userId);
                    $env['userId']    = $objectUser->getId();
                    $env['userLogin'] = $objectUser->getLogin();
                }
                $env['memory'] = memory_get_usage(true);

                $_SERVER['SERVER_NAME'] = $_SERVER['SERVER_NAME'] ?? gethostname();
                $_SERVER['SERVER_ADDR'] = $_SERVER['SERVER_ADDR'] ?? gethostbyname($_SERVER['SERVER_NAME']);

                $envServerKeys = ['SERVER_ADDR', 'SERVER_NAME', 'HTTP_HOST', 'HTTP_REFERER'];
                foreach ($envServerKeys as $value) {
                    if (!empty($_SERVER[$value])) {
                        $env[strtolower($value)] = $_SERVER[$value];
                    }
                }
                $logEnv = ' ' . json_encode($env, $jsonOptions);
            }

            $logText .= $logContent;

            if ($logTextPosEOL === false) {
                $logText .= $logEnv;
            } else {
                $logText = preg_replace('/\n/', $logEnv . PHP_EOL, $logText, 1);
            }
            $result = @file_put_contents($logFile, $logText . PHP_EOL, FILE_APPEND | LOCK_EX);

            return $result ?: 0;
        }
    }