├── .gitignore
├── src
├── views
│ ├── minimal.blade.php
│ └── standard.blade.php
├── TelegramLogger.php
├── TelegramLoggerServiceProvider.php
└── TelegramHandler.php
├── composer.json
├── config
└── telegram-logger.php
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | vendor/
3 | composer.lock
4 |
--------------------------------------------------------------------------------
/src/views/minimal.blade.php:
--------------------------------------------------------------------------------
1 | {{ $appName }} ({{ $level_name }})
2 | {{ $formatted }}
--------------------------------------------------------------------------------
/src/views/standard.blade.php:
--------------------------------------------------------------------------------
1 | {{ $appName }} ({{ $level_name }})
2 | Env: {{ $appEnv }}
3 | [{{ $datetime->format('Y-m-d H:i:s') }}] {{ $appEnv }}.{{ $level_name }} {{ $formatted }}
--------------------------------------------------------------------------------
/src/TelegramLogger.php:
--------------------------------------------------------------------------------
1 | env('TELEGRAM_LOGGER_BOT_TOKEN'),
6 |
7 | // Telegram chat id
8 | 'chat_id' => env('TELEGRAM_LOGGER_CHAT_ID'),
9 |
10 | // Telegram message thread id
11 | 'message_thread_id' => env('TELEGRAM_LOGGER_MESSAGE_THREAD_ID', null),
12 |
13 | // Blade Template to use formatting logs
14 | 'template' => env('TELEGRAM_LOGGER_TEMPLATE', 'laravel-telegram-logging::standard'),
15 |
16 | // Proxy server
17 | 'proxy' => env('TELEGRAM_LOGGER_PROXY', ''),
18 |
19 | // Telegram API host without trailling slash
20 | 'api_host' => env('TELEGRAM_LOGGER_API_HOST', 'https://api.telegram.org'),
21 |
22 | // Telegram sendMessage options: https://core.telegram.org/bots/api#sendmessage
23 | 'options' => [
24 | // 'parse_mode' => 'html',
25 | // 'disable_web_page_preview' => true,
26 | // 'disable_notification' => false
27 | ]
28 | ];
29 |
--------------------------------------------------------------------------------
/src/TelegramLoggerServiceProvider.php:
--------------------------------------------------------------------------------
1 | mergeConfigFrom(__DIR__ . '/../config/telegram-logger.php', 'telegram-logger');
21 | }
22 |
23 | /**
24 | * Perform post-registration booting of services.
25 | *
26 | * @return void
27 | */
28 | public function boot()
29 | {
30 | $this->loadViewsFrom(__DIR__.'/views', 'laravel-telegram-logging');
31 | $this->publishes([__DIR__.'/views' => base_path('resources/views/vendor/laravel-telegram-logging')], 'views');
32 | $this->publishes([__DIR__ . '/../config/telegram-logger.php' => config_path('telegram-logger.php')], 'config');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Darius Matulionis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Telegram logger
2 |
3 | Send logs to Telegram chat via Telegram bot
4 |
5 | ## Install
6 |
7 | ```
8 |
9 | composer require grkamil/laravel-telegram-logging
10 |
11 | ```
12 |
13 | Define Telegram Bot Token and chat id (users telegram id) and set as environment parameters.
14 | Add to .env
15 |
16 | ```
17 | TELEGRAM_LOGGER_BOT_TOKEN=id:token
18 | TELEGRAM_LOGGER_CHAT_ID=chat_id
19 | ```
20 |
21 |
22 | Add to config/logging.php file new channel:
23 |
24 | ```php
25 | 'telegram' => [
26 | 'driver' => 'custom',
27 | 'via' => Logger\TelegramLogger::class,
28 | 'level' => 'debug',
29 | ]
30 | ```
31 |
32 | If your default log channel is a stack, you can add it to the stack channel like this
33 | ```php
34 | 'stack' => [
35 | 'driver' => 'stack',
36 | 'channels' => ['single', 'telegram'],
37 | ]
38 | ```
39 |
40 | Or you can simply change the default log channel in the .env
41 | ```
42 | LOG_CHANNEL=telegram
43 | ```
44 |
45 | Publish config file and views
46 | ```
47 | php artisan vendor:publish --provider "Logger\TelegramLoggerServiceProvider"
48 | ```
49 |
50 | ## Telegram Logging Formats
51 |
52 | You can choose among two different formats that you can specify in the `.env` file like this :
53 |
54 | ```
55 | # Use a minimal log template
56 | TELEGRAM_LOGGER_TEMPLATE = laravel-telegram-logging::minimal
57 |
58 | # Or use the backward compatible one (default setting used even without inserting this row)
59 | TELEGRAM_LOGGER_TEMPLATE = laravel-telegram-logging::standard
60 | ```
61 |
62 | It is possible to create other blade templates and reference them in the `TELEGRAM_LOGGER_TEMPLATE` entry
63 |
64 | ## Create bot
65 |
66 | For using this package you need to create Telegram bot
67 |
68 | 1. Go to @BotFather in the Telegram
69 | 2. Send ``/newbot``
70 | 3. Set up name and bot-name for your bot.
71 | 4. Get token and add it to your .env file (it is written above)
72 | 5. Go to your bot and send ``/start`` message
73 |
74 | ## Change log template at runtime
75 |
76 | 1. Change config for template.
77 | ```php
78 | config(['telegram-logger.template'=>'laravel-telegram-logging::custom'])
79 | ```
80 | 2. Use `Log` as usual.
81 |
82 | ## Configuring a different chat id or token per channel
83 |
84 | 1. Add `chat_id` or `token` to channels in `config/logging.php`. Overrides `config('telegram.chat_id')`.
85 | ```php
86 | [
87 | 'channels' => [
88 | [
89 | 'company' => [
90 | 'driver' => 'custom',
91 | 'via' => TelegramLogger::class,
92 | 'chat_id' => env('TELEGRAM_COMPANY_CHAT_ID'),
93 | 'token' => env('TELEGRAM_COMPANY_BOT_TOKEN'),
94 | 'level' => 'debug'
95 | ],
96 |
97 | 'operations' => [
98 | 'driver' => 'custom',
99 | 'via' => TelegramLogger::class,
100 | 'chat_id' => env('TELEGRAM_OPERATIONS_CHAT_ID'),
101 | 'token' => env('TELEGRAM_OPERATIONS_BOT_TOKEN'),
102 | 'level' => 'debug'
103 | ]
104 | ]
105 | ]
106 | ]
107 | ```
108 |
109 | 2. Use `Log` as usual.
110 | ## Lumen support
111 |
112 | To make it work with Lumen, you need also run two steps:
113 |
114 | 1. Place config/telegram-logger.php file with following code:
115 | ```php
116 | env('TELEGRAM_LOGGER_BOT_TOKEN'),
121 |
122 | // Telegram chat id
123 | 'chat_id' => env('TELEGRAM_LOGGER_CHAT_ID'),
124 |
125 | // you can define your custom template for message
126 | // e.g: logging.template
127 | // 'template' => 'some your view path'
128 | ];
129 | ```
130 |
131 | 2. Uncomment ```$app->withFacades();``` and configure the file ```$app->configure('telegram-logger');``` at bootstrap/app.php
132 | 3. Place default Laravel/Lumen logging file to config/logging.php (to add new channel).
133 |
134 | ## Proxy support
135 | To use a proxy server, set the variable in the .env
136 | ```
137 | TELEGRAM_LOGGER_PROXY=proxy_server.com:port
138 | ```
--------------------------------------------------------------------------------
/src/TelegramHandler.php:
--------------------------------------------------------------------------------
1 | config = $config;
73 | $this->botToken = $this->getConfigValue('token');
74 | $this->chatId = $this->getConfigValue('chat_id');
75 | $this->messageThreadId = $this->getConfigValue('message_thread_id');
76 |
77 | // define variables for text message
78 | $this->appName = config('app.name');
79 | $this->appEnv = config('app.env');
80 | }
81 |
82 | /**
83 | * @param array $record
84 | */
85 | public function write($record): void
86 | {
87 | if (!$this->botToken || !$this->chatId) {
88 | throw new \InvalidArgumentException('Bot token or chat id is not defined for Telegram logger');
89 | }
90 |
91 | // trying to make request and send notification
92 | try {
93 | $textChunks = str_split($this->formatText($record), 4096);
94 |
95 | foreach ($textChunks as $textChunk) {
96 | $this->sendMessage($textChunk);
97 | }
98 | } catch (Exception $exception) {
99 | \Log::channel('single')->error($exception->getMessage());
100 | }
101 | }
102 |
103 | /**
104 | * {@inheritDoc}
105 | */
106 | protected function getDefaultFormatter(): FormatterInterface
107 | {
108 | return new LineFormatter("%message% %context% %extra%\n", null, false, true);
109 | }
110 |
111 | /**
112 | * @param $record
113 | * @return string
114 | */
115 | private function formatText($record): string
116 | {
117 | if ($template = config('telegram-logger.template')) {
118 | if ($record instanceof LogRecord) {
119 | return view($template, array_merge($record->toArray(), [
120 | 'appName' => $this->appName,
121 | 'appEnv' => $this->appEnv,
122 | 'formatted' => $record->formatted,
123 | ])
124 | )->render();
125 | }
126 |
127 | return view($template, array_merge($record, [
128 | 'appName' => $this->appName,
129 | 'appEnv' => $this->appEnv,
130 | ])
131 | )->render();
132 | }
133 |
134 | return sprintf("%s (%s)\n%s", $this->appName, $record['level_name'], $record['formatted']);
135 | }
136 |
137 | /**
138 | * @param string $text
139 | */
140 | private function sendMessage(string $text): void
141 | {
142 | $httpQuery = http_build_query(array_merge(
143 | [
144 | 'text' => $text,
145 | 'chat_id' => $this->chatId,
146 | 'message_thread_id' => $this->messageThreadId,
147 | 'parse_mode' => 'html',
148 | ],
149 | config('telegram-logger.options', [])
150 | ));
151 |
152 | $host = $this->getConfigValue('api_host');
153 |
154 | $url = $host . '/bot' . $this->botToken . '/sendMessage?' . $httpQuery;
155 |
156 | $proxy = $this->getConfigValue('proxy');
157 |
158 | if (!empty($proxy)) {
159 | $context = stream_context_create([
160 | 'http' => [
161 | 'proxy' => $proxy,
162 | ],
163 | ]);
164 | file_get_contents($url, false, $context);
165 | } else {
166 | file_get_contents($url);
167 | }
168 | }
169 |
170 | /**
171 | * @param string $key
172 | * @param string $defaultConfigKey
173 | * @return string
174 | */
175 | private function getConfigValue($key, $defaultConfigKey = null): ?string
176 | {
177 | if (isset($this->config[$key])) {
178 | return $this->config[$key];
179 | }
180 |
181 | return config($defaultConfigKey ?: "telegram-logger.$key");
182 | }
183 | }
184 |
--------------------------------------------------------------------------------