Passed
Push — master ( 307b32...353946 )
by Ioannes
01:31
created

Log   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
wmc 49
eloc 106
c 7
b 0
f 1
dl 0
loc 246
rs 8.48

16 Methods

Rating   Name   Duplication   Size   Complexity  
A formatMessage() 0 9 5
A cleanLogs() 0 6 2
A logInnerException() 0 3 1
A error() 0 9 3
A __construct() 0 8 4
A alert() 0 8 2
A notice() 0 9 3
A critical() 0 8 2
A isDebugEnabled() 0 10 4
A warning() 0 9 3
A log() 0 9 3
A getLogger() 0 24 6
A debug() 0 9 3
A getMinErrorLevel() 0 8 3
A info() 0 9 3
A emergency() 0 8 2

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
namespace App;
3
4
use App\Monolog\ArrayFormatter;
5
use Bitrix\Main\Diag\Debug;
0 ignored issues
show
Bug introduced by
The type Bitrix\Main\Diag\Debug was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Bitrix\Main\Error;
0 ignored issues
show
Bug introduced by
The type Bitrix\Main\Error was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Monolog\Handler\StreamHandler;
8
use Monolog\Logger;
9
use Monolog\Registry;
10
use Psr\Log\LoggerInterface;
11
12
class Log implements LoggerInterface {
13
14
    private $channel;
15
    private $minDebugLevel;
16
17
    /**
18
     * @param false $channel
19
     */
20
    public function __construct($channel = false) {
21
22
        $this->minDebugLevel = ($_ENV['APP_DEBUG_LEVEL'] ?: 'DEBUG');
23
        if($channel) {
0 ignored issues
show
introduced by
The condition $channel is always false.
Loading history...
24
            $this->channel = $channel;
25
            //TODO: get channel options
26
        } else {
27
            $this->channel = ($_ENV['APP_LOG_BITRIX_CHANNEL'] ?: 'bitrix');
28
        }
29
    }
30
31
    /**
32
     * @param $message
33
     * @param array $context
34
     */
35
    public function alert($message, $context = [])
36
    {
37
        try {
38
            $logger = $this->getLogger();
39
            $message = $this->formatMessage($message);
40
            $logger->alert($message, (array) $context);
41
        } catch (\Exception $e) {
42
            self::logInnerException($e);
43
        }
44
    }
45
46
    /**
47
     * @param $message
48
     * @param array $context
49
     */
50
    public function critical($message, $context = [])
51
    {
52
        try {
53
            $logger = $this->getLogger();
54
            $message = $this->formatMessage($message);
55
            $logger->critical($message, (array) $context);
56
        } catch (\Exception $e) {
57
            self::logInnerException($e);
58
        }
59
    }
60
61
    /**
62
     * @param $message
63
     * @param array $context
64
     */
65
    public function error($message, $context = [])
66
    {
67
        if ($this->isDebugEnabled(Logger::ERROR)) {
68
            try {
69
                $logger = $this->getLogger();
70
                $message = $this->formatMessage($message);
71
                $logger->error($message, (array) $context);
72
            } catch (\Exception $e) {
73
                self::logInnerException($e);
74
            }
75
        }
76
    }
77
78
    /**
79
     * @param $message
80
     * @param array $context
81
     */
82
    public function warning($message, $context = [])
83
    {
84
        if ($this->isDebugEnabled(Logger::WARNING)) {
85
            try {
86
                $logger = $this->getLogger();
87
                $message = $this->formatMessage($message);
88
                $logger->warning($message, (array) $context);
89
            } catch (\Exception $e) {
90
                self::logInnerException($e);
91
            }
92
        }
93
    }
94
95
    /**
96
     * @param $message
97
     * @param array $context
98
     */
99
    public function notice($message, $context = [])
100
    {
101
        if ($this->isDebugEnabled(Logger::NOTICE)) {
102
            try {
103
                $logger = $this->getLogger();
104
                $message = $this->formatMessage($message);
105
                $logger->notice($message, (array) $context);
106
            } catch (\Exception $e) {
107
                self::logInnerException($e);
108
            }
109
        }
110
    }
111
112
    /**
113
     * @param $message
114
     * @param array $context
115
     */
116
    public function info($message, $context = [])
117
    {
118
        if ($this->isDebugEnabled(Logger::INFO)) {
119
            try {
120
                $logger = $this->getLogger();
121
                $message = $this->formatMessage($message);
122
                $logger->info($message, (array) $context);
123
            } catch (\Exception $e) {
124
                self::logInnerException($e);
125
            }
126
        }
127
    }
128
129
    /**
130
     * @param $message
131
     * @param array $context
132
     */
133
    public function debug($message, $context = [])
134
    {
135
        if ($this->isDebugEnabled(Logger::DEBUG)) {
136
            try {
137
                $logger = $this->getLogger();
138
                $message = $this->formatMessage($message);
139
                $logger->debug($message, (array) $context);
140
            } catch (\Exception $e) {
141
                self::logInnerException($e);
142
            }
143
        }
144
    }
145
146
    public function emergency($message, $context = [])
147
    {
148
        try {
149
            $logger = $this->getLogger();
150
            $message = $this->formatMessage($message);
151
            $logger->emergency($message, (array) $context);
152
        } catch (\Exception $e) {
153
            self::logInnerException($e);
154
        }
155
    }
156
157
    public function log($level, $message, $context = [])
158
    {
159
        if ($this->isDebugEnabled($level)) {
160
            try {
161
                $logger = $this->getLogger();
162
                $message = $this->formatMessage($message);
163
                $logger->log($level, $message, (array) $context);
164
            } catch (\Exception $e) {
165
                self::logInnerException($e);
166
            }
167
        }
168
    }
169
170
    /**
171
     * @param $message
172
     * @return string
173
     */
174
    private function formatMessage($message) {
175
176
        if($message instanceof \Exception || $message instanceof Error) {
177
            $message = (string) $message;
178
        } else if(is_array($message) || is_object($message)) {
179
            $message = json_encode((array) $message, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
180
            $message = str_replace('\\u0000', '', $message);
181
        }
182
        return (string) $message;
183
    }
184
185
    /**
186
     * @return Logger
187
     */
188
    public function getLogger() {
189
190
        if(Registry::hasLogger($this->channel)) {
191
            return Registry::getInstance($this->channel);
192
        }
193
        $logPath = $_SERVER['DOCUMENT_ROOT'] . ($_ENV['APP_LOG_FOLDER'] ?: '/log/');
194
        $logPath .= $this->channel . '/' . date('Y-m-d') . '.log';
195
        $logDir = pathinfo($logPath, PATHINFO_DIRNAME);
196
        if(!file_exists($logDir)) {
0 ignored issues
show
Bug introduced by
It seems like $logDir can also be of type array; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
        if(!file_exists(/** @scrutinizer ignore-type */ $logDir)) {
Loading history...
197
            $mode = 0775;
198
            if(defined('BX_DIR_PERMISSIONS') && BX_DIR_PERMISSIONS) {
0 ignored issues
show
Bug introduced by
The constant App\BX_DIR_PERMISSIONS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
199
                $mode = BX_DIR_PERMISSIONS;
200
            }
201
            mkdir($logDir, $mode, true);
0 ignored issues
show
Bug introduced by
It seems like $logDir can also be of type array; however, parameter $directory of mkdir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

201
            mkdir(/** @scrutinizer ignore-type */ $logDir, $mode, true);
Loading history...
202
        }
203
204
        $handler = new StreamHandler($logPath);
205
        $handler->setFormatter(new ArrayFormatter());
206
207
        $logger = new Logger($this->channel);
208
        $logger->pushHandler($handler);
209
        Registry::addLogger($logger, $this->channel, true);
210
211
        return $logger;
212
    }
213
214
    /**
215
     * @return int|mixed
216
     */
217
    private function getMinErrorLevel() {
218
219
        $levels = Logger::getLevels();
220
221
        if($this->minDebugLevel && isset($levels[$this->minDebugLevel])) {
222
            return $levels[$this->minDebugLevel];
223
        } else {
224
            return Logger::DEBUG;
225
        }
226
    }
227
228
    /**
229
     * @param int $level
230
     * @return bool
231
     */
232
    private function isDebugEnabled($level = 0)
233
    {
234
        if (defined('FORCE_DEBUG') && FORCE_DEBUG) {
0 ignored issues
show
Bug introduced by
The constant App\FORCE_DEBUG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
235
            return true;
236
        }
237
        $min_level = $this->getMinErrorLevel();
238
        if($level >= $min_level) {
239
            return true;
240
        }
241
        return false;
242
    }
243
244
    /**
245
     * @param \Exception $exception
246
     */
247
    public static function logInnerException(\Exception $exception)
248
    {
249
        Debug::writeToFile((string) $exception, "", "inner_error.log");
250
    }
251
252
    public static function cleanLogs($daysAgo = 15) {
253
254
        $logPath = $_SERVER['DOCUMENT_ROOT'] . ($_ENV['APP_LOG_FOLDER'] ?: '/log/');
255
        $command = sprintf("find %s -mindepth 1 -type f -mtime +%d | xargs rm", $logPath, $daysAgo);
256
        exec($command);
257
        return sprintf('\App\Log::cleanLogs(%d);', $daysAgo);
258
    }
259
}
260