PsrTarget::export()   C
last analyzed

Complexity

Conditions 12
Paths 81

Size

Total Lines 42
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 12
eloc 26
c 6
b 0
f 0
nc 81
nop 0
dl 0
loc 42
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace samdark\log;
3
4
use Psr\Log\LoggerAwareInterface;
5
use Psr\Log\LoggerAwareTrait;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\LogLevel;
8
use yii\base\InvalidConfigException;
9
use yii\helpers\VarDumper;
10
use yii\log\Logger;
11
use yii\log\Target;
12
13
/**
14
 * PsrTarget is a log target which passes messages to PSR-3 compatible logger.
15
 *
16
 * @author Alexander Makarov <[email protected]>
17
 */
18
class PsrTarget extends Target implements LoggerAwareInterface
19
{
20
    use LoggerAwareTrait;
21
22
    /**
23
     * @var bool If enabled, logger use original timestamp from buffer
24
     * @since 1.1.0
25
     */
26
    public $addTimestampToContext = false;
27
28
    /**
29
     * @var bool If enabled, exception's trace will extract into `trace` property
30
     */
31
    public $extractExceptionTrace = false;
32
33
    private $_levelMap = [
34
        Logger::LEVEL_ERROR => LogLevel::ERROR,
35
        Logger::LEVEL_WARNING => LogLevel::WARNING,
36
        Logger::LEVEL_INFO => LogLevel::INFO,
37
        Logger::LEVEL_TRACE => LogLevel::DEBUG,
38
        Logger::LEVEL_PROFILE => LogLevel::DEBUG,
39
        Logger::LEVEL_PROFILE_BEGIN => LogLevel::DEBUG,
40
        Logger::LEVEL_PROFILE_END => LogLevel::DEBUG,
41
42
        // Psr Levels
43
        LogLevel::EMERGENCY => LogLevel::EMERGENCY,
44
        LogLevel::ALERT => LogLevel::ALERT,
45
        LogLevel::CRITICAL => LogLevel::CRITICAL,
46
        LogLevel::ERROR => LogLevel::ERROR,
47
        LogLevel::WARNING => LogLevel::WARNING,
48
        LogLevel::NOTICE => LogLevel::NOTICE,
49
        LogLevel::INFO => LogLevel::INFO,
50
        LogLevel::DEBUG => LogLevel::DEBUG,
51
    ];
52
53
    /**
54
     * @var array
55
     */
56
    private $_levels = [];
57
58
    public function __construct($config = [])
59
    {
60
        $this->_levels = $this->_levelMap;
61
        parent::__construct($config);
62
    }
63
64
    /**
65
     * @return LoggerInterface
66
     * @throws InvalidConfigException
67
     */
68
    public function getLogger()
69
    {
70
        if ($this->logger === null) {
71
            throw new InvalidConfigException('Logger should be configured with Psr\Log\LoggerInterface.');
72
        }
73
        return $this->logger;
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function export()
80
    {
81
        foreach ($this->messages as $message) {
82
            $level = $message[1];
83
84
            $context = [];
85
            if (isset($message[4])) {
86
                $context['trace'] = $message[4];
87
            }
88
89
            if (isset($message[5])) {
90
                $context['memory'] = $message[5];
91
            }
92
93
            if (isset($message[2])) {
94
                $context['category'] = $message[2];
95
            }
96
97
            if ($this->addTimestampToContext && isset($message[3])) {
98
                $context['timestamp'] = $message[3];
99
            }
100
101
            $text = $message[0];
102
            if (!is_string($text)) {
103
                // exceptions may not be serializable if in the call stack somewhere is a Closure
104
                if ($text instanceof \Throwable || $text instanceof \Exception) {
105
                    $context['exception'] = $text;
106
                    if ($this->extractExceptionTrace) {
107
                        $context['trace'] = explode(PHP_EOL, $text->getTraceAsString());
108
                        $text = $text->getMessage();
109
                    } else {
110
                        $text = (string)$text;
111
                    }
112
                } elseif ($text instanceof PsrMessage) {
113
                    $context = array_merge($text->getContext(), $context); // Will not replace standard context keys
114
                    $text = $text->getMessage();
115
                } else {
116
                    $text = VarDumper::export($text);
117
                }
118
            }
119
120
            $this->getLogger()->log($this->_levelMap[$level], $text, $context);
121
        }
122
    }
123
124
    public static function filterMessages($messages, $levels = [], $categories = [], $except = [])
125
    {
126
        $filterByLevel = function ($message) use ($levels) {
127
            return isset($levels[$message[1]]);
128
        };
129
        return array_filter(parent::filterMessages($messages, 0, $categories, $except), $filterByLevel);
130
    }
131
132
    public function getLevels()
133
    {
134
        return $this->_levels;
135
    }
136
137
    /**
138
     * Sets the message levels that this target is interested in.
139
     *
140
     * The parameter can be an array.
141
     * Valid level names include: 'error',
142
     * 'warning', 'info', 'trace' and 'profile'; valid level values include:
143
     * [[Logger::LEVEL_ERROR]], [[Logger::LEVEL_WARNING]], [[Logger::LEVEL_INFO]],
144
     * [[Logger::LEVEL_TRACE]], [[Logger::LEVEL_PROFILE]] and Psr Log levels:
145
     * [[LogLevel::EMERGENCY]], [[LogLevel::ALERT]], [[LogLevel::CRITICAL]],
146
     * [[LogLevel::ERROR]], [[LogLevel::WARNING]], [[LogLevel::NOTICE]],
147
     * [[LogLevel::INFO]] and [[LogLevel::DEBUG]].
148
     *
149
     * For example,
150
     *
151
     * ```php
152
     * ['error', 'warning', LogLevel::CRITICAL, LogLevel::EMERGENCY]
153
     * ```
154
     *
155
     * @param array $levels message levels that this target is interested in.
156
     * @throws InvalidConfigException if $levels value is not correct.
157
     */
158
    public function setLevels($levels)
159
    {
160
        static $levelMap = [
161
            'error' => Logger::LEVEL_ERROR,
162
            'warning' => Logger::LEVEL_WARNING,
163
            'info' => Logger::LEVEL_INFO,
164
            'trace' => Logger::LEVEL_TRACE,
165
            'profile' => Logger::LEVEL_PROFILE,
166
        ];
167
168
        if (is_array($levels)) {
0 ignored issues
show
introduced by
The condition is_array($levels) is always true.
Loading history...
169
            $intrestingLevels = [];
170
            
171
            foreach ($levels as $level) {
172
                if (!isset($this->_levels[$level]) && !isset($levelMap[$level])) {
173
                    throw new InvalidConfigException("Unrecognized level: $level");
174
                }
175
176
                if (isset($levelMap[$level])) {
177
                    $intrestingLevels[$levelMap[$level]] = $this->_levels[$levelMap[$level]];
178
                }
179
180
                if (isset($this->_levels[$level])) {
181
                    $intrestingLevels[$level] = $this->_levels[$level];
182
                }
183
            }
184
            
185
            $this->_levels = $intrestingLevels;
186
        } else {
187
            throw new InvalidConfigException("Incorrect $levels value");
188
        }
189
    }
190
}
191