]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
тестирование логов
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 1 Nov 2024 09:12:15 +0000 (12:12 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 1 Nov 2024 09:12:15 +0000 (12:12 +0300)
erp24/actions/log/CollectAction.php
erp24/config/web.php
erp24/controllers/TestLogController.php [new file with mode: 0644]
erp24/log/Message.php [new file with mode: 0644]
erp24/log/TelegramTarget.php [new file with mode: 0644]
erp24/services/InfoLogService.php
erp24/services/LogService.php
erp24/services/TelegramService.php
erp24/services/TelegramTarget.php
erp24/views/test-log/index.php [new file with mode: 0644]

index b87a6e2719a16754539efaaf754daacf454c8fe5..5cd86e999cd6bcf39083add455163d8037313bab 100755 (executable)
@@ -29,31 +29,93 @@ class CollectAction extends Action
         ]);
         // Сохраняем лог в базе данных
         if ($log->save()) {
+
+            // Проверка на наличие аналогичных записей перед отправкой в Telegram
+            if (!self::shouldSendToTelegram($log)) {
+                return; // Пропускаем отправку, если уже есть записи за текущую дату
+            }
+
             // Формируем сообщение для отправки в Telegram с использованием MarkdownV2
-            $errorMessage = sprintf(
-                "*JavaScript Error Detected*\n\n" .
-                "*URL:*\n```%s```\n\n" .
-                "*Created At:*\n```%s```\n\n" .
-                "*IP:*\n```%s```\n\n" .
-                "*User Agent:*\n```%s```\n\n" .
-                "*File:* `%s`\n" .
-                "*Line:* `%s`, *Column:* `%s`\n" .
-                "*Message:*\n```%s```\n\n" .
-                "*Context:*\n```%s```",
-                $this->controller->request->getReferrer() ?? '<no referrer>',
-                date('Y-m-d H:i:s', $log->log_time),
-                $log->ip,
-                $log->user_agent,
-                $log->file ?? '<no file>',
-                $log->line ?? '<no line>',
-                $log->col ?? '<no col>',
-                $log->message,
-                $log->context ?? '<no context>'
-            );
+            $errorMessage = "⚠️*Ошибка JavaScript Обнаружена*⚠️\n\n";
+
+// Добавляем строки в сообщение только если параметры присутствуют
+            if ($url = $this->controller->request->getReferrer()) {
+                $errorMessage .= "*URL:*\n```" . self::escapeMarkdown($url) . "```\n\n";
+            }
+
+            if ($createdAt = date('Y-m-d H:i:s', $log->log_time)) {
+                $errorMessage .= "*Created At:*\n```" . self::escapeMarkdown($createdAt) . "```\n\n";
+            }
+
+            if ($ip = $log->ip) {
+                $errorMessage .= "*IP:*\n```" . self::escapeMarkdown($ip) . "```\n\n";
+            }
+
+            if ($userAgent = $log->user_agent) {
+                $errorMessage .= "*User Agent:*\n```" . self::escapeMarkdown($userAgent) . "```\n\n";
+            }
+
+            if ($file = $log->file) {
+                $errorMessage .= "*File:*\n```" . self::escapeMarkdown($file) . "```\n\n";
+            }
+
+            if ($line = $log->line) {
+                $errorMessage .= "*Line:*\n```" . self::escapeMarkdown($line) . "```\n\n";
+            }
+
+            if ($col = $log->col) {
+                $errorMessage .= "*Column:*\n```" . self::escapeMarkdown($col) . "```\n\n";
+            }
+
+            if ($message = $log->message) {
+                $errorMessage .= "*Message:*\n```" . self::escapeMarkdown($message) . "```\n\n";
+            }
+
+            if ($context = $log->context) {
+                $errorMessage .= "*Context:*\n```" . self::escapeMarkdown($context) . "```\n\n";
+            }
+
+
+
+            $disableNotification = false;
 
             // Отправляем сообщение об ошибке в Telegram через TelegramService
-            TelegramService::sendErrorToTelegramMessage($errorMessage);
+            TelegramService::sendErrorToTelegramMessage($errorMessage, $disableNotification);
+        }
+    }
+
+// Метод для проверки наличия аналогичных записей в ErrorLog за текущую дату
+    private static function shouldSendToTelegram($log)
+    {
+        $startOfDay = strtotime('today'); // Метка времени для начала текущего дня
+
+        // Запрос в таблицу ErrorLog для поиска аналогичных записей
+        $count = ErrorLog::find()
+            ->where([
+                'ip' => $log->ip,
+                'category' => $log->category,
+                'level' => $log->level,
+                'referrer' => $log->referrer,
+                'user_agent' => $log->user_agent,
+                'file' => $log->file,
+                'line' => $log->line,
+                'col' => $log->col,
+                'message' => $log->message,
+                'context' => $log->context,
+            ])
+            ->andWhere(['>=', 'log_time', $startOfDay]) // Фильтр по началу текущего дня
+            ->count();
+
+        return $count <= 1; // Отправляем только если нет более одной записи
+    }
+
+    private static function escapeMarkdown($text)
+    {
+        $specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
+        foreach ($specialChars as $char) {
+            $text = str_replace($char, '\\' . $char, $text);
         }
+        return $text;
     }
 
 }
index 51b09cc92d74083b133435b1d615819117a44e48..b4a1b6a8f351480ceeaace69b26acee4adbe9d85 100644 (file)
@@ -62,7 +62,7 @@ $config = [
                     'levels' => ['error', 'warning'],
                 ],
                 [
-                    'class' => 'yii_app\services\TelegramTarget',
+                    'class' => 'app\log\TelegramTarget',
                     'levels' => ['error', 'warning'],
                    // 'categories' => ['api.error', 'js.error', 'command.error'],
                 ],
diff --git a/erp24/controllers/TestLogController.php b/erp24/controllers/TestLogController.php
new file mode 100644 (file)
index 0000000..ec97850
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+namespace app\controllers;
+
+use Yii;
+use yii\web\Controller;
+use yii_app\records\ApiErrorLog;
+use yii_app\records\ErrorLog;
+use yii_app\records\InfoLog;
+
+
+use yii_app\services\InfoLogService;
+use yii_app\services\LogService;
+
+class TestLogController extends Controller
+{
+    /**
+     * Действие для выбора типа ошибки и создания копии записи в соответствующей таблице.
+     */
+    public function actionGenerateLog($type)
+    {
+        switch ($type) {
+            case 'api_error':
+                $this->generateApiErrorLog();
+                break;
+
+            case 'error_log':
+                $this->generateErrorLog();
+                break;
+
+            case 'info_log':
+                $this->generateInfoLog();
+                break;
+
+            default:
+                throw new \yii\web\BadRequestHttpException("Invalid log type specified.");
+        }
+
+        return $this->redirect(['index']);
+    }
+
+    /**
+     * Создает копию записи в таблице ApiErrorLog с текущей датой.
+     */
+    protected function generateApiErrorLog()
+    {
+        $existingLog = ApiErrorLog::find()->orderBy(['created_at' => SORT_DESC])->one();
+        if ($existingLog) {
+            LogService::apiErrorLog($existingLog->payload); // Используем метод из LogService
+        }
+    }
+
+    /**
+     * Создает копию записи в таблице ErrorLog с текущей датой.
+     */
+    protected function generateErrorLog()
+    {
+        $existingLog = ErrorLog::find()->orderBy(['log_time' => SORT_DESC])->one();
+        if ($existingLog) {
+            $logController = new \app\controllers\LogController('log-controller', Yii::$app); // экземпляр контроллера
+            $action = new \yii_app\actions\log\CollectAction('collect', $logController);
+            $action->run(); // Запускаем действие, чтобы создать копию
+        }
+    }
+
+    /**
+     * Создает копию записи в таблице InfoLog с текущей датой.
+     */
+    protected function generateInfoLog()
+    {
+        $existingLog = InfoLog::find()->orderBy(['created_at' => SORT_DESC])->one();
+        if ($existingLog) {
+            InfoLogService::setInfoLog($existingLog->file, $existingLog->line, $existingLog->message, $existingLog->context);
+        }
+    }
+
+    /**
+     * Действие для отображения представления с кнопками.
+     */
+    public function actionIndex()
+    {
+        return $this->render('index');
+    }
+}
\ No newline at end of file
diff --git a/erp24/log/Message.php b/erp24/log/Message.php
new file mode 100644 (file)
index 0000000..fbc27b3
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+
+namespace app\log;
+
+use yii\base\BaseObject;
+use yii\base\InvalidConfigException;
+use yii\helpers\VarDumper;
+use yii\log\Logger;
+
+class Message extends BaseObject
+{
+    /**
+     * @var array raw message.
+     */
+    public $message;
+
+    /**
+     * @var bool whether the current request is a console request.
+     */
+    private $_isConsoleRequest;
+
+    public function __construct($message, $config = [])
+    {
+        $this->message = $message;
+        parent::__construct($config);
+    }
+
+    /**
+     * Returns the message category.
+     * @return string message category.
+     */
+    public function getCategory()
+    {
+        return $this->message[2];
+    }
+
+    /**
+     * Returns the command line.
+     * @return string|null command line, `null` if not available.
+     */
+    public function getCommandLine()
+    {
+        if (\Yii::$app === null || !$this->getIsConsoleRequest()) {
+            return null;
+        }
+
+        $params = [];
+        if (isset($_SERVER['argv'])) {
+            $params = $_SERVER['argv'];
+        }
+        return implode(' ', $params);
+    }
+
+    /**
+     * Returns whether the current request is a console request.
+     * @return bool whether the current request is a console request.
+     * @throws InvalidConfigException if unable to determine.
+     */
+    public function getIsConsoleRequest()
+    {
+        if ($this->_isConsoleRequest === null && \Yii::$app !== null) {
+            if (\Yii::$app->getRequest() instanceof \yii\console\Request) {
+                $this->_isConsoleRequest = true;
+            } elseif (\Yii::$app->getRequest() instanceof \yii\web\Request) {
+                $this->_isConsoleRequest = false;
+            }
+        }
+        if ($this->_isConsoleRequest === null) {
+            throw new InvalidConfigException('Unable to determine if the application is a console or web application.');
+        }
+
+        return $this->_isConsoleRequest;
+    }
+
+    /**
+     * Returns the message level as a string.
+     * @return string message level as a string.
+     */
+    public function getLevel()
+    {
+        return Logger::getLevelName($this->message[0][1]);
+    }
+
+    /**
+     * Returns a string to be prefixed to the message.
+     * @return string messsage prefix string.
+     */
+    public function getPrefix()
+    {
+        if ($this->target !== null) {
+            return $this->target->getMessagePrefix($this->message);
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Returns the session ID.
+     * @return string|null session ID, `null` if not available.
+     */
+    public function getSessionId()
+    {
+        if (
+            \Yii::$app !== null
+            && \Yii::$app->has('session', true)
+            && \Yii::$app->getSession() !== null
+            && \Yii::$app->getSession()->getIsActive()
+        ) {
+            return \Yii::$app->getSession()->getId();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the additional stack trace as a string.
+     * @return string|null stack trace, `null` if not available.
+     */
+    public function getStackTrace()
+    {
+        if (!isset($this->message[4]) || empty($this->message[4])) {
+            return null;
+        }
+
+        $traces = array_map(function ($trace) {
+            return "in {$trace['file']}:{$trace['line']}";
+        }, $this->message[4]);
+        return implode("\n", $traces);
+    }
+
+    /**
+     * Returns the message text.
+     * @return string message text.
+     */
+    public function getText()
+    {
+        $text = $this->message[0];
+        if (!is_string($text)) {
+            if ($text instanceof \Throwable) {
+                $text = (string) $text;
+            } else {
+                $text = VarDumper::export($text);
+            }
+        }
+        return $text;
+    }
+
+    /**
+     * Returns the message creation timestamp.
+     * @return float message creation timestamp.
+     */
+    public function getTimestamp()
+    {
+        return $this->message[3];
+    }
+
+    /**
+     * Returns the current absolute URL.
+     * @return null|string absolute URL, `null` if not available.
+     * @throws InvalidConfigException
+     */
+    public function getUrl()
+    {
+        if (\Yii::$app === null || $this->getIsConsoleRequest()) {
+            return null;
+        }
+
+        return \Yii::$app->getRequest()->getAbsoluteUrl();
+    }
+
+    /**
+     * Returns the user identity ID.
+     * @return int|string|null user identity ID, `null` if not available.
+     */
+    public function getUserId()
+    {
+        if (
+            \Yii::$app !== null
+            && \Yii::$app->has('user', true)
+            && \Yii::$app->getUser() !== null
+        ) {
+            $user = \Yii::$app->getUser()->getIdentity(false);
+            if ($user !== null) {
+                return $user->getId();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the user IP address.
+     * @return string|null user IP address, `null` if not available.
+     */
+    public function getUserIp()
+    {
+        if (\Yii::$app === null || $this->getIsConsoleRequest()) {
+            return null;
+        }
+
+        return \Yii::$app->getRequest()->getUserIP();
+    }
+}
\ No newline at end of file
diff --git a/erp24/log/TelegramTarget.php b/erp24/log/TelegramTarget.php
new file mode 100644 (file)
index 0000000..044247c
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+
+namespace app\log;
+
+use Yii;
+use yii\base\InvalidConfigException;
+use yii\base\InvalidValueException;
+use yii\log\Logger;
+use app\log\Message;
+use yii_app\services\TelegramService;
+
+class TelegramTarget extends \yii\log\Target
+{
+    public bool $enable = true;
+
+    /**
+     * @var string bot token.
+     * @see https://core.telegram.org/bots/api#authorizing-your-bot
+     */
+
+
+    /**
+     * @var int|string unique identifier for the target chat or username of the target channel
+     * (in the format `{@}channelusername`).
+     */
+
+
+    private array $levelEmojis = [
+        Logger::LEVEL_ERROR => "☠ ",
+        Logger::LEVEL_WARNING => "⚠ ",
+        Logger::LEVEL_INFO => "ℹ ",
+        Logger::LEVEL_TRACE => "📝 ",
+    ];
+
+
+    private $errorTrackingFile = '@runtime/logs/error_tracking.log';
+
+// Метод для проверки и записи уникальной ошибки
+    private function shouldSendMessage($currentError)
+    {
+        $filePath = Yii::getAlias($this->errorTrackingFile);
+        $currentDate = date('Y-m-d');
+        $errorExists = false;
+        $errorLines = [];
+
+        // Загружаем существующие ошибки, если файл существует
+        if (file_exists($filePath)) {
+            $errorLines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+        }
+
+        // Создаём хеш текущей ошибки после нормализации текста
+        $normalizedCurrentError = $this->normalizeText($currentError);
+        $currentErrorHash = md5($normalizedCurrentError);
+
+        foreach ($errorLines as &$line) {
+            [$date, $count, $hash, $errorText] = explode('|', $line, 4);
+
+            // Сравниваем хеши
+            if ($hash === $currentErrorHash) {
+                $errorExists = true;
+
+                // Если ошибка уже была за текущую дату
+                if ($date === $currentDate && $count >= 1) {
+                    return false; // Не отправляем
+                }
+
+                // Увеличиваем счётчик и обновляем дату
+                $count++;
+                $line = implode('|', [$currentDate, $count, $hash, $errorText]);
+                break;
+            }
+        }
+
+        // Если ошибка новая, добавляем её в список
+        if (!$errorExists) {
+            $errorLines[] = implode('|', [$currentDate, 1, $currentErrorHash, $currentError]);
+        }
+
+        // Сохраняем обновлённый список ошибок
+        file_put_contents($filePath, implode(PHP_EOL, $errorLines) . PHP_EOL);
+
+        return true; // Ошибка не найдена или обновлена, можно отправлять
+    }
+
+// Метод для нормализации текста ошибки
+    private function normalizeText($text)
+    {
+        // Приводим текст к единому формату: нижний регистр, удаление лишних пробелов
+        $text = strtolower($text);
+        $text = preg_replace('/\s+/', ' ', $text);
+        return trim($text);
+    }
+
+    /**
+     * @throws InvalidConfigException
+     */
+    public function export()
+    {
+        if (!$this->enable) {
+            return;
+        }
+
+
+
+        $message = new Message($this->messages[0]);
+        $errorText = $message->getText();
+
+
+        // Проверка наличия подобных сообщений
+        if (!$this->shouldSendMessage($errorText)) {
+            return; // Пропускаем отправку, если ошибка уже зарегистрирована
+        }
+
+        // Формирование уровня и основного сообщения
+        $level = isset($this->levelEmojis[$message->message[1]]) ? $this->levelEmojis[$message->message[1]] . ' ' : '*' . ucfirst($message->getLevel()) . '* @ ';
+        if ($message->getIsConsoleRequest()) {
+            $level .= '```' . $message->getCommandLine() . '```';
+        } else {
+            $level .= '[' . $message->getUrl() . '](' . $message->getUrl() . ')';
+        }
+
+        // Текст сообщения
+        $text = [
+            $level,
+            " ",
+            "```" . mb_substr($message->getText(), 0, 3300) . "```",
+            " ",
+            "```" . $message->getStackTrace() . "```",
+            "🙂 " . $message->getUserIp(),
+        ];
+
+        $formattedMessage = implode("\n", $text);
+
+        // Настройка уведомления для сообщений уровня ERROR
+        $disableNotification = $message->message[1] !== Logger::LEVEL_ERROR;
+
+        // Отправка сообщения через TelegramService
+        try {
+            TelegramService::sendErrorToTelegramMessage($formattedMessage, $disableNotification);
+        } catch (\Exception $e) {
+            throw new InvalidValueException(
+                'Unable to send logs to Telegram: ' . $e->getMessage(), $e->getCode()
+            );
+        }
+    }
+}
\ No newline at end of file
index 6aaae416f812860f536abd0b132710cdb99da195..6b9795df2f841e13822060f58797fe68682daf5f 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace yii_app\services;
 
+use yii\db\Expression;
 use yii_app\records\InfoLog;
 
 class InfoLogService
@@ -22,24 +23,73 @@ class InfoLogService
             ->setMessage($messageText)
             ->setLogTime()
             ->setCreatedAt();
+
+
+
         // Валидация и сохранение лога в базе данных
         if ($infoLog->validate() && $infoLog->save()) {
-            // Форматируем сообщение для отправки в Telegram
-            $telegramMessage = sprintf(
-                "*Info Log Detected*\n\n" .
-                "*File:* `%s`\n" .
-                "*Line:* `%s`\n" .
-                "*Message:*\n```%s```\n\n" .
-                "*Context:*\n```%s```",
-                $file ?? '<no file>',
-                $line ?? '<no line>',
-                $messageText,
-                $context ?? '<no context>'
-            );
 
+            // Проверяем, нужно ли отправлять сообщение в Telegram
+            if (!self::shouldSendToTelegram($file, $line, $messageText, $context)) {
+                return; // Пропускаем отправку, если уже есть записи за текущую дату
+            }
+
+            // Формируем сообщение для отправки в Telegram
+            $telegramMessage = "⚠️*Сообщение из InfoLog*⚠️\n\n";
+
+            // Добавляем строки в сообщение только если параметры присутствуют
+            if ($file) {
+                $telegramMessage .= "*File:*\n```" . self::escapeMarkdown($file) . "```\n\n";
+            }
+
+            if ($line) {
+                $telegramMessage .= "*Line:*\n```" . self::escapeMarkdown($line) . "```\n\n";
+            }
+
+            if ($messageText) {
+                $telegramMessage .= "*Сообщение:*\n```log" . self::escapeMarkdown($messageText) . "```\n\n";
+            }
+
+            if ($context) {
+                $telegramMessage .= "*Context:*\n```log" . self::escapeMarkdown($context) . "```\n\n";
+            }
+
+
+            $disableNotification = false;
             // Отправляем сообщение в Telegram
-            TelegramService::sendErrorToTelegramMessage($telegramMessage);
+            TelegramService::sendErrorToTelegramMessage($telegramMessage, $disableNotification);
         }
     }
 
+
+    // Метод для экранирования символов MarkdownV2
+    private static function escapeMarkdown($text)
+    {
+        $specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
+        foreach ($specialChars as $char) {
+            $text = str_replace($char, '\\' . $char, $text);
+        }
+        return $text;
+    }
+
+
+    // Метод для проверки, существуют ли подобные записи в InfoLog за текущую дату
+    private static function shouldSendToTelegram($file, $line, $messageText, $context)
+    {
+        $currentDate = date('Y-m-d');
+
+        // Выполняем запрос, чтобы найти записи с такими же значениями за текущую дату
+        $count = InfoLog::find()
+            ->where([
+                'file' => $file,
+                'line' => $line,
+                'message' => $messageText,
+                'context' => $context,
+            ])
+            ->andWhere(['>=', 'created_at', new Expression("DATE('$currentDate')")])
+            ->count();
+
+        return $count <= 1; // Возвращаем true, только если нет более одной записи
+    }
+
 }
\ No newline at end of file
index efee9ec749e82c0ad45f35bb8a2fda9c5128c780..f4c75019e7d49c9eb61e2383a6e29fbcc5ad8a2a 100644 (file)
@@ -62,21 +62,36 @@ class LogService
             $apiErrorLog->ip = Yii::$app->request->remoteIP ?? '<no ip>';
             $apiErrorLog->save();
 
-            // Форматируем сообщение об ошибке для Telegram с использованием MarkdownV2
-            $errorMessage = sprintf(
-                "*API Error Detected*\n\n" .
-                "*URL:*\n```%s```\n\n" .
-                "*Created At:*\n```%s```\n\n" .
-                "*IP:*\n```%s```\n\n" .
-                "*Payload:*\n```json\n%s```",
-                $apiErrorLog->url,
-                $apiErrorLog->created_at,
-                $apiErrorLog->ip,
-                $jsonString
-            );
-
-            // Отправляем сообщение об ошибке в Telegram
-            TelegramService::sendErrorToTelegramMessage($errorMessage);
+            // Проверка на наличие аналогичной записи перед созданием новой и отправкой в Telegram
+            if (!self::shouldSendToTelegram($hash_input, $jsonString)) {
+                return; // Пропускаем отправку, если уже есть аналогичная запись за текущую дату
+            }
+
+
+            // Форматирование сообщения об ошибке с условным добавлением строк
+            $errorMessage = "⚠️*Ошибка API Обнаружена*⚠️\n\n";
+
+            // Добавляем строки только если параметры присутствуют
+            if ($url = $apiErrorLog->url) {
+                $errorMessage .= "*URL:*\n```" . self::escapeMarkdown($url) . "```\n\n";
+            }
+
+            if ($createdAt = $apiErrorLog->created_at) {
+                $errorMessage .= "*Created At:*\n```" . $createdAt . "```\n\n";
+            }
+
+            if ($ip = $apiErrorLog->ip) {
+                $errorMessage .= "*IP:*\n```" . self::escapeMarkdown($ip) . "```\n\n";
+            }
+
+            if ($jsonString) {
+                $errorMessage .= "*Payload:*\n```json\n" . $jsonString . "```\n\n";
+            }
+
+
+            $disableNotification = false;
+            // Отправляем сообщение об ошибке в Telegram через TelegramService
+            TelegramService::sendErrorToTelegramMessage($errorMessage, $disableNotification);
 
 
         } else {
@@ -85,4 +100,37 @@ class LogService
             $h->save();
         }
     }
+
+
+// Метод для экранирования символов MarkdownV2
+    private static function escapeMarkdown($text)
+    {
+        $specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
+        foreach ($specialChars as $char) {
+            $text = str_replace($char, '\\' . $char, $text);
+        }
+        return $text;
+    }
+
+
+// Метод для проверки наличия аналогичных записей в ApiErrorLog за текущую дату
+    private static function shouldSendToTelegram($hash_input, $jsonString)
+    {
+        $startOfDay = strtotime('today'); // Метка времени для начала текущего дня
+
+        // Запрос в таблицу ApiErrorLog для поиска аналогичных записей за текущую дату
+        $count = ApiErrorLog::find()
+            ->where([
+                'hash_input' => $hash_input,
+                'url' => Yii::$app->request->url ?? '<no url>',
+                'ip' => Yii::$app->request->remoteIP ?? '<no ip>',
+                'payload' => $jsonString,
+            ])
+            ->andWhere(['>=', 'created_at', date('Y-m-d H:i:s', $startOfDay)]) // Фильтр по началу текущего дня
+            ->count();
+
+        return $count <= 1; // Отправляем только если нет более одной записи
+    }
+
+
 }
index c75dc0c5d80f11a0926f1edd1f72013929772b5f..fc79c4c77c493eeffbbba3e9df4a9fac1d13c2a9 100644 (file)
@@ -20,19 +20,20 @@ class TelegramService {
         return $client->request('GET', $url);
     }
 
-public static function sendErrorToTelegramMessage($message)
+public static function sendErrorToTelegramMessage($message,$disableNotification)
 {
     $botToken = self::TELEGRAM_API_URL;
     $chatId = self::CHAT_CHANNEL_ID;
     $apiURL = "https://api.telegram.org/bot{$botToken}/sendMessage";
-
+    //$message = self::escapeMarkdown($message);
     $client = new Client();
     try {
         $client->post($apiURL, [
             'json' => [
                 'chat_id' => $chatId,
                 'text' => $message,
-                'parse_mode' => 'MarkdownV2'
+                'parse_mode' => 'MarkdownV2',
+                'disable_notification' => $disableNotification,
             ],
         ]);
     } catch (\Exception $e) {
@@ -41,4 +42,20 @@ public static function sendErrorToTelegramMessage($message)
 }
 
 
+    // Метод для экранирования символов MarkdownV2
+    private static function escapeMarkdown($text)
+    {
+        // Экранирование символов, зарезервированных в MarkdownV2
+        $specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
+
+        foreach ($specialChars as $char) {
+            // Проверяем, что символ не находится внутри кода
+            $text = preg_replace_callback('/(?<!`)([' . preg_quote($char) . '])(?!`)/', function ($matches) {
+                return '\\' . $matches[1];
+            }, $text);
+        }
+        return $text;
+    }
+
+
 }
\ No newline at end of file
index 7a97526a4d024e288c0abdd0daa6fe872db30a22..1699d878bc77b2d93f14ad3900f637841bd6c35e 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace yii_app\services;
 
+use yii\log\Logger;
 use yii\log\Target;
 use Yii;
 use GuzzleHttp\Client;
@@ -12,6 +13,8 @@ class TelegramTarget extends Target
     public $botToken = "8063257458:AAGnMf4cxwJWlYLF1wS_arn4PrOaLs9ERQQ";
     public $chatId ="-1001861631125";
 
+
+
     public function export()
     {
         $apiURL = 'https://api.telegram.org/bot' . $this->botToken . '/sendMessage';
diff --git a/erp24/views/test-log/index.php b/erp24/views/test-log/index.php
new file mode 100644 (file)
index 0000000..57be5ce
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+use yii\helpers\Html;
+
+/* @var $this yii\web\View */
+
+$this->title = 'Тестирование логов';
+?>
+
+<div class="site-index p-4">
+  <h1><?= $this->title  ?></h1>
+
+    <div class="log-buttons">
+        <?= Html::a('Отправить API Error Log', ['test-log/generate-log', 'type' => 'api_error'], ['class' => 'btn btn-danger']) ?>
+        <?= Html::a('Отправить Error Log', ['test-log/generate-log', 'type' => 'error_log'], ['class' => 'btn btn-warning']) ?>
+        <?= Html::a('Отправить Info Log', ['test-log/generate-log', 'type' => 'info_log'], ['class' => 'btn btn-info']) ?>
+    </div>
+</div>
\ No newline at end of file