Completed
Push — 6.0 ( c1d76c...33b2e4 )
by liu
06:02
created

Log   F

Complexity

Total Complexity 61

Size/Duplication

Total Lines 458
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 115
c 3
b 0
f 0
dl 0
loc 458
ccs 0
cts 127
cp 0
rs 3.52
wmc 61

23 Methods

Rating   Name   Duplication   Size   Complexity  
A getConfig() 0 3 1
A processor() 0 3 1
A __construct() 0 14 3
A driver() 0 12 4
A channel() 0 22 5
A close() 0 7 2
A error() 0 3 1
A log() 0 3 1
A clear() 0 9 2
A alert() 0 3 1
B record() 0 30 11
A info() 0 3 1
A getLog() 0 4 2
A notice() 0 3 1
A warning() 0 3 1
B saveChannel() 0 26 7
A append() 0 13 5
A write() 0 17 4
A emergency() 0 3 1
A debug() 0 3 1
A critical() 0 3 1
A save() 0 15 4
A sql() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Log often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Log, and based on these observations, apply Extract Interface, too.

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