Test Failed
Push — 6.0 ( 28e2fd...aac0a6 )
by liu
04:04
created

Log::debug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use InvalidArgumentException;
16
use Psr\Log\LoggerInterface;
17
18
/**
19
 * 日志管理类
20
 */
21
class Log implements LoggerInterface
22
{
23
    const EMERGENCY = 'emergency';
24
    const ALERT     = 'alert';
25
    const CRITICAL  = 'critical';
26
    const ERROR     = 'error';
27
    const WARNING   = 'warning';
28
    const NOTICE    = 'notice';
29
    const INFO      = 'info';
30
    const DEBUG     = 'debug';
31
    const SQL       = 'sql';
32
33
    /**
34
     * 日志信息
35
     * @var array
36
     */
37
    protected $log = [];
38
39
    /**
40
     * 日志通道
41
     * @var array
42
     */
43
    protected $channel = [];
44
45
    /**
46
     * 配置参数
47
     * @var array
48
     */
49
    protected $config = [];
50
51
    /**
52
     * 日志写入驱动
53
     * @var array
54
     */
55
    protected $driver = [];
56
57
    /**
58
     * 日志处理
59
     *
60
     * @var array
61
     */
62
    protected $processor = [
63
        '*' => [],
64
    ];
65
66
    /**
67
     * 关闭日志(渠道)
68
     * @var array
69
     */
70
    protected $close = [];
71
72
    /**
73
     * (通道)允许写入类型
74
     * @var array
75
     */
76
    protected $allow = [];
77
78
    /**
79
     * 是否控制台执行
80
     * @var bool
81
     */
82 6
    protected $isCli = false;
83
84 6
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $app should have a doc-comment as per coding-style.
Loading history...
85
     * 构造方法
86 6
     * @access public
87
     */
88
    public function __construct(App $app)
89
    {
90 6
        $this->config = $app->config->get('log');
91
92
        if (isset($this->config['processor'])) {
93
            $this->processor($this->config['processor']);
94 6
        }
95 6
96
        if (!empty($this->config['close'])) {
97
            $this->close['*'] = true;
98
        }
99
100
        if (!empty($this->config['level'])) {
101
            $this->allow['*'] = $this->config['level'];
102
        }
103
104
        $this->isCli = $app->runningInConsole();
105
        $this->channel();
106
    }
107
108
    /**
109
     * 获取日志配置
110
     * @access public
111
     * @return array
112
     */
113
    public function getConfig(): array
114
    {
115
        return $this->config;
116
    }
117
118
    /**
119
     * 注册一个日志回调处理
120
     *
121
     * @param  callable $callback 回调
122
     * @param  string   $channel  日志通道名
123
     * @return void
124
     */
125
    public function processor(callable $callback, string $channel = '*'): void
126 6
    {
127
        $this->processor[$channel][] = $callback;
128 6
    }
129 6
130
    /**
131
     * 切换日志通道
132 6
     * @access public
133 6
     * @param  string|array $name 日志通道名
134
     * @return $this
135
     */
136
    public function channel($name = '')
137
    {
138
        if ('' == $name) {
139
            $name = $this->config['default'] ?? 'think';
140
        }
141
142
        $names = (array) $name;
143
144
        foreach ($names as $name) {
145
            if (!isset($this->config['channels'][$name])) {
146
                throw new InvalidArgumentException('Undefined log config:' . $name);
147
            }
148
149
            $config = $this->config['channels'][$name];
150
151
            if (isset($config['processor'])) {
152
                $this->processor($config['processor'], $name);
153
            }
154
155
            if (!empty($config['close'])) {
156
                $this->close[$name] = true;
157
            }
158
159
            if (!empty($config['level'])) {
160
                $this->allow[$name] = $config['level'];
161
            }
162
        }
163
164
        $this->channel = $names;
165
        return $this;
166
    }
167
168
    /**
169
     * 实例化日志写入驱动
170
     * @access public
171
     * @param  string $name 日志通道名
172
     * @return object
173
     */
174
    protected function driver(string $name)
175
    {
176
        if (!isset($this->driver[$name])) {
177
            $config = $this->config['channels'][$name];
178
            $type   = !empty($config['type']) ? $config['type'] : 'File';
179
180
            $this->driver[$name] = App::factory($type, '\\think\\log\\driver\\', $config);
181
        }
182
183
        return $this->driver[$name];
184
    }
185
186
    /**
187
     * 获取日志信息
188
     * @access public
189
     * @param  string $channel 日志通道
190
     * @return array
191
     */
192
    public function getLog(string $channel = ''): array
193
    {
194
        $channel = $channel ?: array_shift($this->channel);
195
        return $this->log[$channel] ?? [];
196
    }
197
198
    /**
199
     * 记录日志信息
200
     * @access public
201
     * @param  mixed  $msg       日志信息
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 7 found
Loading history...
202
     * @param  string $type      日志级别
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 6 found
Loading history...
203
     * @param  array  $context   替换内容
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
204
     * @return $this
205
     */
206
    public function record($msg, string $type = 'info', array $context = [])
207
    {
208
        if (is_string($msg) && !empty($context)) {
209
            $replace = [];
210
            foreach ($context as $key => $val) {
211
                $replace['{' . $key . '}'] = $val;
212
            }
213
214
            $msg = strtr($msg, $replace);
215
        }
216
217
        if (isset($this->config['type_channel'][$type])) {
218
            $channels = (array) $this->config['type_channel'][$type];
219
        } else {
220
            $channels = $this->channel;
221
        }
222
223
        if (!empty($this->allow['*']) && !in_array($type, $this->allow['*'])) {
224
            return $this;
225
        }
226
227
        foreach ($channels as $channel) {
228
            if (empty($this->allow[$channel]) || in_array($type, $this->allow[$channel])) {
229
                $this->channelLog($channel, $msg, $type);
230
            }
231
        }
232
233
        return $this;
234
    }
235
236
    /**
237
     * 记录通道日志
238
     * @access public
239
     * @param  string $channel 日志通道
240
     * @param  mixed  $msg  日志信息
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
241
     * @param  string $type 日志级别
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
242
     * @return void
243
     */
244
    protected function channelLog(string $channel, $msg, string $type): void
245
    {
246
        if (!empty($this->close['*']) || !empty($this->close[$channel])) {
247
            return;
248
        }
249
250
        if ($this->isCli || !empty($this->config['channels'][$channel]['realtime_write'])) {
251
            // 实时写入
252
            $this->write($msg, $type, true, $channel);
253
        } else {
254
            $this->log[$channel][$type][] = $msg;
255
        }
256
    }
257
258
    /**
259
     * 清空日志信息
260
     * @access public
261
     * @param  string  $channel 日志通道名
262
     * @return $this
263
     */
264
    public function clear(string $channel = '')
265
    {
266
        if ($channel) {
267
            $this->log[$channel] = [];
268
        } else {
269
            $this->log = [];
270
        }
271
272
        return $this;
273
    }
274
275
    /**
276
     * 关闭本次请求日志写入
277
     * @access public
278
     * @param  string  $channel 日志通道名
279
     * @return $this
280
     */
281
    public function close(string $channel = '*')
282
    {
283
        $this->close[$channel] = true;
284
285
        $this->clear('*' == $channel ? '' : $channel);
286
287
        return $this;
288
    }
289
290
    /**
291
     * 保存日志信息
292
     * @access public
293
     * @return bool
294
     */
295
    public function save(): bool
296
    {
297
        if (!empty($this->close['*'])) {
298
            return true;
299
        }
300
301
        foreach ($this->log as $channel => $logs) {
302
            $result = $this->saveChannel($channel, $logs);
303
304
            if ($result) {
305
                $this->log[$channel] = [];
306
            }
307
        }
308
309
        return true;
310
    }
311
312
    /**
313
     * 保存某个通道的日志信息
314
     * @access protected
315
     * @param  string $channel 日志通道名
316
     * @param  array  $log    日志信息
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 4 found
Loading history...
317
     * @return bool
318
     */
319
    protected function saveChannel(string $channel, array $log = []): bool
320
    {
321
        if (!empty($this->close[$channel])) {
322
            return false;
323
        }
324
325
        // 日志处理
326
        $processors = $this->processor[$channel] ?? $this->processor['*'];
327
328
        foreach ($processors as $callback) {
329
            $log = $callback($log, $channel, $this);
330
331
            if (false === $log) {
332
                return false;
333
            }
334
        }
335
336
        return $this->driver($channel)->save($log);
337
    }
338
339
    /**
340
     * 实时写入日志信息
341
     * @access public
342
     * @param  mixed  $msg   调试信息
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 3 found
Loading history...
343
     * @param  string $type  日志级别
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 2 found
Loading history...
344
     * @param  bool   $force 是否强制写入
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
345
     * @param  string $channel  日志通道
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
346
     * @return bool
347
     */
348
    public function write($msg, string $type = 'info', bool $force = false, $channel = ''): bool
349
    {
350
        if (empty($this->allow['*'])) {
351
            $force = true;
352
        }
353
354
        $log = [];
355
356
        if (true === $force || in_array($type, $this->allow['*'])) {
357
            $log[$type][] = $msg;
358
        } else {
359
            return false;
360
        }
361
362
        // 写入日志
363
        $channels = $channel ? (array) $channel : $this->channel;
364
365
        foreach ($channels as $channel) {
366
            if (empty($this->allow[$channel]) || in_array($type, $this->allow[$channel])) {
367
                $this->saveChannel($channel, $log);
368
            }
369
        }
370
371
        return true;
372
    }
373
374
    /**
375
     * 记录日志信息
376
     * @access public
377
     * @param  string $level     日志级别
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 5 found
Loading history...
378
     * @param  mixed  $message   日志信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
379
     * @param  array  $context   替换内容
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 3 found
Loading history...
380
     * @return void
381
     */
382
    public function log($level, $message, array $context = []): void
383
    {
384
        $this->record($message, $level, $context);
385
    }
386
387
    /**
388
     * 记录emergency信息
389
     * @access public
390
     * @param  mixed $message 日志信息
391
     * @param  array $context 替换内容
392
     * @return void
393
     */
394
    public function emergency($message, array $context = []): void
395
    {
396
        $this->log(__FUNCTION__, $message, $context);
397
    }
398
399
    /**
400
     * 记录警报信息
401
     * @access public
402
     * @param  mixed $message 日志信息
403
     * @param  array $context 替换内容
404
     * @return void
405
     */
406
    public function alert($message, array $context = []): void
407
    {
408
        $this->log(__FUNCTION__, $message, $context);
409
    }
410
411
    /**
412
     * 记录紧急情况
413
     * @access public
414
     * @param  mixed $message 日志信息
415
     * @param  array $context 替换内容
416
     * @return void
417
     */
418
    public function critical($message, array $context = []): void
419
    {
420
        $this->log(__FUNCTION__, $message, $context);
421
    }
422
423
    /**
424
     * 记录错误信息
425
     * @access public
426
     * @param  mixed $message 日志信息
427
     * @param  array $context 替换内容
428
     * @return void
429
     */
430
    public function error($message, array $context = []): void
431
    {
432
        $this->log(__FUNCTION__, $message, $context);
433
    }
434
435
    /**
436
     * 记录warning信息
437
     * @access public
438
     * @param  mixed $message 日志信息
439
     * @param  array $context 替换内容
440
     * @return void
441
     */
442
    public function warning($message, array $context = []): void
443
    {
444
        $this->log(__FUNCTION__, $message, $context);
445
    }
446
447
    /**
448
     * 记录notice信息
449
     * @access public
450
     * @param  mixed $message 日志信息
451
     * @param  array $context 替换内容
452
     * @return void
453
     */
454
    public function notice($message, array $context = []): void
455
    {
456
        $this->log(__FUNCTION__, $message, $context);
457
    }
458
459
    /**
460
     * 记录一般信息
461
     * @access public
462
     * @param  mixed $message 日志信息
463
     * @param  array $context 替换内容
464
     * @return void
465
     */
466
    public function info($message, array $context = []): void
467
    {
468
        $this->log(__FUNCTION__, $message, $context);
469
    }
470
471
    /**
472
     * 记录调试信息
473
     * @access public
474
     * @param  mixed $message 日志信息
475
     * @param  array $context 替换内容
476
     * @return void
477
     */
478
    public function debug($message, array $context = []): void
479
    {
480
        $this->log(__FUNCTION__, $message, $context);
481
    }
482
483
    /**
484
     * 记录sql信息
485
     * @access public
486
     * @param  mixed $message 日志信息
487
     * @param  array $context 替换内容
488
     * @return void
489
     */
490
    public function sql($message, array $context = []): void
491
    {
492
        $this->log(__FUNCTION__, $message, $context);
493
    }
494
495
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __call()
Loading history...
496
    {
497
        array_unshift($args, $method);
498
        call_user_func_array([$this, 'log'], $args);
499
    }
500
}
501