1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the TelegramBot package. |
4
|
|
|
* |
5
|
|
|
* (c) Avtandil Kikabidze aka LONGMAN <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Longman\TelegramBot; |
12
|
|
|
|
13
|
|
|
use Longman\TelegramBot\Exception\TelegramLogException; |
14
|
|
|
use Monolog\Formatter\LineFormatter; |
15
|
|
|
use Monolog\Handler\HandlerInterface; |
16
|
|
|
use Monolog\Handler\StreamHandler; |
17
|
|
|
use Monolog\Logger; |
18
|
|
|
|
19
|
|
|
class TelegramLog |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* Monolog instance |
23
|
|
|
* |
24
|
|
|
* @var Logger |
25
|
|
|
*/ |
26
|
|
|
static protected $monolog; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Monolog instance for update |
30
|
|
|
* |
31
|
|
|
* @var Logger |
32
|
|
|
*/ |
33
|
|
|
static protected $monolog_update; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Path for error log |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
static protected $error_log_path; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Path for debug log |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
static protected $debug_log_path; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Path for update log |
51
|
|
|
* |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
static protected $update_log_path; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Temporary stream handle for debug log |
58
|
|
|
* |
59
|
|
|
* @var resource|null |
60
|
|
|
*/ |
61
|
|
|
static protected $debug_log_temp_stream_handle; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Initialize |
65
|
|
|
* |
66
|
|
|
* Initilize monolog instance. Singleton |
67
|
|
|
* Is possbile provide an external monolog instance |
68
|
|
|
* |
69
|
|
|
* @param Logger $external_monolog |
70
|
|
|
* |
71
|
|
|
* @return Logger |
72
|
|
|
*/ |
73
|
3 |
|
public static function initialize(Logger $external_monolog = null) |
74
|
|
|
{ |
75
|
3 |
|
if (self::$monolog === null) { |
76
|
3 |
|
if ($external_monolog !== null) { |
77
|
1 |
|
self::$monolog = $external_monolog; |
78
|
|
|
} else { |
79
|
2 |
|
self::$monolog = new Logger('bot_log'); |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
3 |
|
return self::$monolog; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Initialize update |
88
|
|
|
* |
89
|
|
|
* Initilize monolog update instance. Singleton |
90
|
|
|
* Is possbile provide an external monolog instance |
91
|
|
|
* |
92
|
|
|
* @param Logger $external_monolog |
93
|
|
|
* |
94
|
|
|
* @return Logger |
95
|
|
|
*/ |
96
|
1 |
|
public static function initializeUpdate(Logger $external_monolog = null) |
97
|
|
|
{ |
98
|
1 |
|
if (self::$monolog_update === null) { |
99
|
1 |
|
if ($external_monolog !== null) { |
100
|
|
|
self::$monolog_update = $external_monolog; |
101
|
|
|
} else { |
102
|
1 |
|
self::$monolog_update = new Logger('bot_update_log'); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
1 |
|
return self::$monolog_update; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Initialize error log |
111
|
|
|
* |
112
|
|
|
* @param string $path |
113
|
|
|
* @param HandlerInterface $external_handler |
114
|
|
|
* |
115
|
|
|
* @return Logger |
116
|
|
|
* @throws TelegramLogException |
117
|
|
|
*/ |
118
|
2 |
View Code Duplication |
public static function initErrorLog($path, HandlerInterface $external_handler = null) |
|
|
|
|
119
|
|
|
{ |
120
|
2 |
|
if ($path === null || $path === '') { |
121
|
1 |
|
throw new TelegramLogException('Empty path for error log'); |
122
|
|
|
} |
123
|
1 |
|
self::initialize(); |
124
|
1 |
|
self::$error_log_path = $path; |
125
|
|
|
|
126
|
1 |
|
if (is_null($external_handler)) { |
127
|
1 |
|
$handler = new StreamHandler(self::$error_log_path, Logger::ERROR); |
128
|
|
|
} else { |
129
|
|
|
$handler = $external_handler; |
130
|
|
|
} |
131
|
|
|
|
132
|
1 |
|
return self::$monolog->pushHandler($handler->setFormatter(new LineFormatter(null, null, true))); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Initialize debug log |
137
|
|
|
* |
138
|
|
|
* @param string $path |
139
|
|
|
* @param HandlerInterface $external_handler |
140
|
|
|
* |
141
|
|
|
* @return Logger |
142
|
|
|
* @throws TelegramLogException |
143
|
|
|
*/ |
144
|
2 |
View Code Duplication |
public static function initDebugLog($path, HandlerInterface $external_handler = null) |
|
|
|
|
145
|
|
|
{ |
146
|
2 |
|
if ($path === null || $path === '') { |
147
|
1 |
|
throw new TelegramLogException('Empty path for debug log'); |
148
|
|
|
} |
149
|
1 |
|
self::initialize(); |
150
|
1 |
|
self::$debug_log_path = $path; |
151
|
|
|
|
152
|
1 |
|
if (is_null($external_handler)) { |
153
|
1 |
|
$handler = new StreamHandler(self::$debug_log_path, Logger::DEBUG); |
154
|
|
|
} else { |
155
|
|
|
$handler = $external_handler; |
156
|
|
|
} |
157
|
|
|
|
158
|
1 |
|
return self::$monolog->pushHandler($handler->setFormatter(new LineFormatter(null, null, true))); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Get the stream handle of the temporary debug output |
163
|
|
|
* |
164
|
|
|
* @return mixed The stream if debug is active, else false |
165
|
|
|
*/ |
166
|
|
|
public static function getDebugLogTempStream() |
167
|
|
|
{ |
168
|
|
|
if (self::$debug_log_temp_stream_handle === null) { |
169
|
|
|
if (!self::isDebugLogActive()) { |
170
|
|
|
return false; |
171
|
|
|
} |
172
|
|
|
self::$debug_log_temp_stream_handle = fopen('php://temp', 'w+b'); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
return self::$debug_log_temp_stream_handle; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Write the temporary debug stream to log and close the stream handle |
180
|
|
|
* |
181
|
|
|
* @param string $message Message (with placeholder) to write to the debug log |
182
|
|
|
*/ |
183
|
|
|
public static function endDebugLogTempStream($message = '%s') |
184
|
|
|
{ |
185
|
|
|
if (is_resource(self::$debug_log_temp_stream_handle)) { |
186
|
|
|
rewind(self::$debug_log_temp_stream_handle); |
187
|
|
|
self::debug($message, stream_get_contents(self::$debug_log_temp_stream_handle)); |
188
|
|
|
fclose(self::$debug_log_temp_stream_handle); |
189
|
|
|
self::$debug_log_temp_stream_handle = null; |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Initialize update log |
195
|
|
|
* |
196
|
|
|
* Initilize monolog instance. Singleton |
197
|
|
|
* Is possbile provide an external monolog instance |
198
|
|
|
* |
199
|
|
|
* @param string $path |
200
|
|
|
* @param HandlerInterface $external_handler |
201
|
|
|
* |
202
|
|
|
* @return Logger |
203
|
|
|
* @throws TelegramLogException |
204
|
|
|
*/ |
205
|
2 |
|
public static function initUpdateLog($path, HandlerInterface $external_handler = null) |
206
|
|
|
{ |
207
|
2 |
|
if ($path === null || $path === '') { |
208
|
1 |
|
throw new TelegramLogException('Empty path for update log'); |
209
|
|
|
} |
210
|
1 |
|
self::initializeUpdate(); |
211
|
1 |
|
self::$update_log_path = $path; |
212
|
|
|
|
213
|
1 |
|
if (is_null($external_handler)) { |
214
|
1 |
|
$handler = new StreamHandler(self::$update_log_path, Logger::INFO); |
215
|
|
|
} else { |
216
|
|
|
$handler = $external_handler; |
217
|
|
|
} |
218
|
|
|
|
219
|
1 |
|
return self::$monolog_update->pushHandler($handler->setFormatter(new LineFormatter('%message%' . PHP_EOL))); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Is error log active |
224
|
|
|
* |
225
|
|
|
* @return bool |
226
|
|
|
*/ |
227
|
4 |
|
public static function isErrorLogActive() |
228
|
|
|
{ |
229
|
4 |
|
return self::$error_log_path !== null; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Is debug log active |
234
|
|
|
* |
235
|
|
|
* @return bool |
236
|
|
|
*/ |
237
|
2 |
|
public static function isDebugLogActive() |
238
|
|
|
{ |
239
|
2 |
|
return self::$debug_log_path !== null; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Is update log active |
244
|
|
|
* |
245
|
|
|
* @return bool |
246
|
|
|
*/ |
247
|
1 |
|
public static function isUpdateLogActive() |
248
|
|
|
{ |
249
|
1 |
|
return self::$update_log_path !== null; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Report error log |
254
|
|
|
* |
255
|
|
|
* @param string $text |
256
|
|
|
*/ |
257
|
4 |
|
public static function error($text) |
258
|
|
|
{ |
259
|
4 |
|
if (self::isErrorLogActive()) { |
260
|
4 |
|
$text = self::getLogText($text, func_get_args()); |
261
|
4 |
|
self::$monolog->error($text); |
262
|
|
|
} |
263
|
4 |
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Report debug log |
267
|
|
|
* |
268
|
|
|
* @param string $text |
269
|
|
|
*/ |
270
|
2 |
|
public static function debug($text) |
271
|
|
|
{ |
272
|
2 |
|
if (self::isDebugLogActive()) { |
273
|
2 |
|
$text = self::getLogText($text, func_get_args()); |
274
|
2 |
|
self::$monolog->debug($text); |
275
|
|
|
} |
276
|
2 |
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* Report update log |
280
|
|
|
* |
281
|
|
|
* @param string $text |
282
|
|
|
*/ |
283
|
1 |
|
public static function update($text) |
284
|
|
|
{ |
285
|
1 |
|
if (self::isUpdateLogActive()) { |
286
|
1 |
|
$text = self::getLogText($text, func_get_args()); |
287
|
1 |
|
self::$monolog_update->info($text); |
288
|
|
|
} |
289
|
1 |
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Applies vsprintf to the text if placeholder replacements are passed along. |
293
|
|
|
* |
294
|
|
|
* @param string $text |
295
|
|
|
* @param array $args |
296
|
|
|
* |
297
|
|
|
* @return string |
298
|
|
|
*/ |
299
|
6 |
|
protected static function getLogText($text, array $args = []) |
300
|
|
|
{ |
301
|
|
|
// Pop the $text off the array, as it gets passed via func_get_args(). |
302
|
6 |
|
array_shift($args); |
303
|
|
|
|
304
|
|
|
// Suppress warning if placeholders don't match out. |
305
|
6 |
|
return @vsprintf($text, $args) ?: $text; |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.