Passed
Push — master ( 4bcd98...bef579 )
by 世昌
03:04
created

Debug::canBeStringValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 1
nc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace suda\framework\debug;
4
5
use suda\framework\debug\log\LogLevel;
6
use suda\framework\debug\log\LoggerTrait;
7
use suda\framework\debug\attach\DumpTrait;
8
use suda\framework\debug\attach\AttachTrait;
9
use suda\framework\debug\log\LoggerInterface;
10
use suda\framework\debug\attach\DumpInterface;
11
use suda\framework\debug\log\LoggerAwareTrait;
12
use suda\framework\debug\attach\AttachInterface;
13
use suda\framework\debug\log\LoggerAwareInterface;
14
use Throwable;
15
16
class Debug implements LoggerInterface, LoggerAwareInterface, DumpInterface, AttachInterface, ConfigInterface
17
{
18
    use LoggerTrait, LoggerAwareTrait, DumpTrait, AttachTrait, ConfigTrait;
19
20
    /**
21
     * 忽略堆栈
22
     *
23
     * @var array
24
     */
25
    protected $ignoreTraces = [__DIR__];
26
27
    /**
28
     * 时间记录
29
     *
30
     * @var array
31
     */
32
    protected $timeRecord;
33
34
    public function log(string $level, string $message, array $context = [])
35
    {
36
        $attribute = $this->getAttribute();
37
        $attribute['message'] = $this->strtr($message, $context);
38
        $attribute['level'] = $level;
39
        $caller = new Caller(debug_backtrace(), $this->getIgnoreTraces());
40
        $trace = $caller->getCallerTrace();
41
        $attribute['file'] = $trace['file'];
42
        $attribute['line'] = $trace['line'];
43
        $attribute = $this->assignAttributes($attribute);
44
        $this->logger->log($level, $this->interpolate($this->getConfig('log-format'), $context, $attribute), []);
45
    }
46
47
    /**
48
     * 设置忽略前缀
49
     *
50
     * @return array
51
     */
52
    public function getIgnoreTraces(): array
53
    {
54
        return $this->ignoreTraces;
55
    }
56
57
    public function getDefaultConfig(): array
58
    {
59
        return [
60
            'log-format' => '%time-format% - %memory-format% [%level%] %file%:%line% %message%',
61
            'start-time' => 0,
62
            'start-memory' => 0,
63
        ];
64
    }
65
66
    protected function strtr(string $message, array $context)
67
    {
68
        $replace = [];
69
        foreach ($context as $key => $val) {
70
            if ($this->canBeStringValue($val)) {
71
                $replace['{' . $key . '}'] = $val;
72
            }
73
        }
74
        return strtr($message, $replace);
75
    }
76
77
    protected function canBeStringValue($val) : bool
78
    {
79
        return !is_array($val) && (!is_object($val) || method_exists($val, '__toString'));
80
    }
81
82
    protected function assignAttributes(array $attribute): array
83
    {
84
        $attribute['current-time'] = number_format(microtime(true), 4, '.', '');
85
        $time = microtime(true) - $this->getConfig('start-time');
86
        $memory = memory_get_usage() - $this->getConfig('start-memory');
87
        $attribute['time-format'] = number_format($time, 10, '.', '');
88
        $attribute['memory-format'] = $this->formatBytes($memory, 2);
89
        $attribute['memory'] = $memory;
90
        return $attribute;
91
    }
92
93
    public static function formatBytes(int $bytes, int $precision = 0)
94
    {
95
        $human = ['B', 'KB', 'MB', 'GB', 'TB'];
96
        $bytes = max($bytes, 0);
97
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
98
        $pos = min($pow, count($human) - 1);
99
        $bytes /= (1 << (10 * $pos));
100
        return round($bytes, $precision) . ' ' . $human[$pos];
101
    }
102
103
    public function time(string $name, string $type = LogLevel::INFO)
104
    {
105
        $this->timeRecord[$name] = ['time' => microtime(true), 'level' => $type];
106
    }
107
108
    public function timeEnd(string $name)
109
    {
110
        if (array_key_exists($name, $this->timeRecord)) {
111
            $pass = microtime(true) - $this->timeRecord[$name]['time'];
112
            $this->log(
113
                $this->timeRecord[$name]['level'],
114
                sprintf("process %s cost %ss", $name, number_format($pass, 5))
115
            );
116
            return $pass;
117
        }
118
        return 0;
119
    }
120
121
    /**
122
     * @param array $ignoreTraces
123
     * @return $this
124
     */
125
    public function setIgnoreTraces(array $ignoreTraces)
126
    {
127
        $this->ignoreTraces = $ignoreTraces;
128
        return $this;
129
    }
130
131
132
    /**
133
     * 添加忽略路径
134
     * @param string $path
135
     * @return $this
136
     */
137
    public function addIgnorePath(string $path)
138
    {
139
        $this->ignoreTraces[] = $path;
140
        return $this;
141
    }
142
}
143