├── README.md ├── composer.json ├── config └── tg-logger.php └── src ├── Commands └── TgLoggerCreateTopics.php ├── TgFormatter.php ├── TgHandler.php ├── TgLogger.php ├── TgLoggerMethods.php └── TgLoggerServiceProvider.php /README.md: -------------------------------------------------------------------------------- 1 | # Telegram Logger for Laravel 2 | 3 | A module for Laravel that allows you to send logs to Telegram. 4 | 5 | ## Description 6 | This module allows you to send logs to a Telegram group, breaking them down by topic. You can describe the configuration for the basic log types or write your own logging levels. 7 | 8 | ## Installing the module 9 | The installation is done using Composer: 10 | ```bash 11 | composer require prog-time/tg-logger 12 | ``` 13 | 14 | ## Configuring the module 15 | 1. Create a Telegram bot 16 | 2. Create a Telegram group and include "Topics" in it 17 | 3. Specify the variables in .environment 18 | ```php 19 | TG_LOGGER_TOKEN="token_bot" 20 | TG_LOGGER_CHAT_ID="id_group" 21 | ``` 22 | 4. Add the created bot and grant it administrator rights 23 | 5. Create a configuration file **config/tg-logger.php** manually or using a command. 24 | ```php 25 | php artisan vendor:publish --tag=config 26 | ``` 27 | 6. In **config/tg-logger.php** specify the bot token, the ID of the created group, and describe the topics that need to be created. 28 | ```bash 29 | return [ 30 | 'token' => env('TG_LOGGER_TOKEN'), 31 | 'chat_id' => env('TG_LOGGER_CHAT_ID'), 32 | 'topics' => [ 33 | [ 34 | 'name' => 'Debug messages', 35 | 'icon_color' => '9367192', 36 | 'level' => 'debug', 37 | ], 38 | [ 39 | 'name' => 'Cron tasks', 40 | 'icon_color' => '9367192', 41 | 'level' => 'crone', 42 | ], 43 | [ 44 | 'name' => 'Errors', 45 | 'icon_color' => '9367192', 46 | 'level' => 'error, notice, warning, emergency', 47 | ] 48 | ] 49 | ]; 50 | ``` 51 | 7. Run the command to create themes in a group. After executing this command, the file **config/tg-logger.php** it will be overwritten and the topic IDs for each log type will be indicated in it. 52 | ```bash 53 | php artisan tglogger:create-topics 54 | ``` 55 | 56 | ## Sending any type of error 57 | To catch all types of errors, you need to change the basic log handler in 58 | the configuration file **config/logging.php** by specifying the module classes as handlers. 59 | 60 | ```angular2html 61 | 'channels' => [ 62 | ... 63 | 'telegram' => [ 64 | 'driver' => 'monolog', 65 | 'handler' => ProgTime\TgLogger\TgHandler::class, 66 | 'formatter' => ProgTime\TgLogger\TgFormatter::class, 67 | 'level' => 'debug', 68 | ], 69 | ... 70 | ], 71 | ``` 72 | and in .env, change the **LOG_CHANNEL parameter** 73 | 74 | ```angular2html 75 | LOG_CHANNEL=telegram 76 | ``` 77 | 78 | ## Calling the module operation directly 79 | To work with the module directly, you can use the following code. 80 | 81 | ```php 82 | TgLogger::sendLog('Your message', 'level'); 83 | ``` 84 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prog-time/tg-logger", 3 | "description": "A Laravel package for sending logs to Telegram", 4 | "type": "library", 5 | "license": "MIT", 6 | "minimum-stability": "stable", 7 | "version": "1.0.0", 8 | "prefer-stable": true, 9 | "support": { 10 | "source": "https://github.com/prog-time/tg-logger" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Prog-Time", 15 | "email": "liya-rabota97@mail.ru" 16 | } 17 | ], 18 | "require": { 19 | "php": "^8.0" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "ProgTime\\TgLogger\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "ProgTime\\TgLogger\\TgLoggerServiceProvider" 30 | ] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /config/tg-logger.php: -------------------------------------------------------------------------------- 1 | env('TG_LOGGER_TOKEN'), 5 | 'chat_id' => env('TG_LOGGER_CHAT_ID'), 6 | 'topics' => [ 7 | [ 8 | 'name' => 'Errors', 9 | 'icon_color' => '9367192', 10 | 'level' => 'error, notice, warning, emergency', 11 | ] 12 | ] 13 | ]; 14 | -------------------------------------------------------------------------------- /src/Commands/TgLoggerCreateTopics.php: -------------------------------------------------------------------------------- 1 | call('config:cache'); 17 | 18 | $configSettings = config('tg-logger'); 19 | $topics = config('tg-logger.topics'); 20 | 21 | if (empty($topics)) { 22 | throw new \Exception('Config tg-logger not found!'); 23 | } 24 | 25 | if (empty($topics)) { 26 | throw new \Exception('Topics not found!'); 27 | } 28 | 29 | foreach ($topics as $key => $valueParams) { 30 | $queryParams = [ 31 | 'name' => $valueParams['name'], 32 | 'icon_color' => $valueParams['icon_color'] ?? '', 33 | ]; 34 | 35 | if (!empty($valueParams['id_topic'])) { 36 | $queryParams['message_thread_id'] = (int)$valueParams['id_topic']; 37 | 38 | $resultQuery = (new TgLoggerMethods())->telegramQuery('editForumTopic', $queryParams); 39 | if (isset($resultQuery['ok']) && $resultQuery['error_code']) { 40 | if ($resultQuery['ok'] === false && $resultQuery['error_code'] === 400) { 41 | if (strpos($resultQuery['description'], 'TOPIC_NOT_MODIFIED') !== false) { 42 | continue; 43 | } 44 | } 45 | } 46 | } 47 | 48 | $resultQuery = (new TgLoggerMethods())->telegramQuery('createForumTopic', $queryParams); 49 | if (!empty($resultQuery['result'])) { 50 | $configSettings['topics'][$key]['id_topic'] = $resultQuery['result']['message_thread_id']; 51 | } 52 | } 53 | $this->updateConfigFile($configSettings); 54 | 55 | $this->info('All topics have been created and the configuration has been updated!'); 56 | } catch (\Exception $e) { 57 | $this->info('ERROR: ' . $e->getMessage()); 58 | } 59 | } 60 | 61 | /** 62 | * Changing the tg-logger configuration file 63 | * @param array $configSettings 64 | * @return void 65 | */ 66 | private function updateConfigFile(array $configSettings): void 67 | { 68 | $configPath = config_path('tg-logger.php'); 69 | $updatedContent = "call('config:cache'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/TgFormatter.php: -------------------------------------------------------------------------------- 1 | level->name); 14 | TgLogger::sendLog($record['formatted'], $levelName); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/TgLogger.php: -------------------------------------------------------------------------------- 1 | $topicSettings[$level]['id_topic'], 49 | ]; 50 | 51 | if (is_string($logData)) { 52 | $textMessage = $logData; 53 | $queryParams['text'] = $textMessage; 54 | } else { 55 | $queryParams['text'] = '``` '. print_r($logData, true) .' ```'; 56 | $queryParams['parse_mode'] = 'MarkdownV2'; 57 | } 58 | 59 | (new TgLoggerMethods())->telegramQuery('sendMessage', $queryParams); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/TgLoggerMethods.php: -------------------------------------------------------------------------------- 1 | botToken = config('tg-logger.token'); 29 | 30 | if (empty(config('tg-logger.chat_id'))) { 31 | throw new \Exception('ID chat is missing'); 32 | } 33 | $this->chatId = (int)config('tg-logger.chat_id'); 34 | } catch (\Exception $e) { 35 | echo $e->getMessage(); 36 | } 37 | } 38 | 39 | /** 40 | * Sending POST requests 41 | * @param string $urlQuery 42 | * @param array $queryParams 43 | * @return array|null 44 | */ 45 | protected function postQuery(string $urlQuery, array $queryParams = []): ?array 46 | { 47 | try { 48 | $ch = curl_init($urlQuery); 49 | curl_setopt($ch, CURLOPT_POST, true); 50 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 51 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 52 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 53 | curl_setopt($ch, CURLOPT_POSTFIELDS, $queryParams); 54 | $resultQuery = curl_exec($ch); 55 | curl_close($ch); 56 | 57 | if (empty($resultQuery)) { 58 | throw new \Exception('Запрос вызвал ошибку'); 59 | } 60 | 61 | return json_decode($resultQuery, true) ?? null; 62 | } catch (\Exception $e) { 63 | return null; 64 | } 65 | } 66 | 67 | /** 68 | * Sending requests to Telegram 69 | * @param string $method - request method 70 | * @param array $queryParams - request parameters 71 | * @return array|null 72 | */ 73 | public function telegramQuery(string $method, array $queryParams = []): ?array 74 | { 75 | try { 76 | $urlQuery = "https://api.telegram.org/bot{$this->botToken}/{$method}"; 77 | 78 | $queryParams['chat_id'] = $this->chatId; 79 | $resultQuery = $this->postQuery($urlQuery, $queryParams); 80 | 81 | if (empty($resultQuery)) { 82 | throw new \Exception('Запрос вызвал ошибку'); 83 | } 84 | 85 | return $resultQuery; 86 | } catch (\Exception $e) { 87 | return null; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/TgLoggerServiceProvider.php: -------------------------------------------------------------------------------- 1 | mergeConfigFrom(__DIR__ . '/../config/tg-logger.php', 'tg-logger'); 16 | } 17 | 18 | /** 19 | * Bootstrap the application services. 20 | */ 21 | public function boot() 22 | { 23 | if ($this->app->runningInConsole()) { 24 | $this->commands([ 25 | TgLoggerCreateTopics::class, 26 | ]); 27 | 28 | $this->publishes([ 29 | __DIR__ . '/../config/tg-logger.php' => config_path('tg-logger.php'), 30 | ], 'config'); 31 | } 32 | } 33 | } 34 | --------------------------------------------------------------------------------