Test Failed
Push — master ( e4b2c6...b343ab )
by Fran
02:49
created

Logger::checkLogLevel()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 24
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 18.6216

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 21
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 24
ccs 8
cts 21
cp 0.381
crap 18.6216
rs 8.6506
1
<?php
2
3
namespace PSFS\base;
4
5
use Monolog\Formatter\LineFormatter;
6
use Monolog\Handler\FirePHPHandler;
7
use Monolog\Handler\StreamHandler;
8
use Monolog\Logger as Monolog;
9
use Monolog\Processor\MemoryUsageProcessor;
10
use Monolog\Processor\UidProcessor;
11
use PSFS\base\config\Config;
12
use PSFS\base\exception\ConfigException;
13
use PSFS\base\exception\GeneratorException;
14
use PSFS\base\types\helpers\GeneratorHelper;
15
use PSFS\base\types\helpers\Inspector;
16
use PSFS\base\types\helpers\SlackHelper;
17
use PSFS\base\types\traits\SingletonTrait;
18
19
20
if (!defined('LOG_DIR')) {
21
    GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
22
    define('LOG_DIR', BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
23
}
24
25
/**
26
 * Class Logger
27
 * @package PSFS\base
28
 * Servicio de log
29
 */
30
class Logger
31
{
32
    const DEFAULT_NAMESPACE = 'PSFS';
33
    use SingletonTrait;
34
    /**
35
     * @var \Monolog\Logger
36
     */
37
    protected $logger;
38
    /**
39
     * @var resource
40
     */
41
    private $stream;
42
    /**
43
     * @var UidProcessor
44
     */
45
    private $uuid;
46
    /**
47
     * @var string
48
     */
49
    protected $logLevel;
50
51
    /**
52
     * Logger constructor.
53
     * @throws GeneratorException
54
     * @throws ConfigException
55
     */
56 1
    public function __construct()
57
    {
58 1
        $args = func_get_args();
59 1
        list($logger, $debug, $path) = $this->setup($args);
60 1
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', 'a+');
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen($path . PSFS\base\...('Ymd') . '.log', 'a+') can also be of type false. However, the property $stream is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
61 1
        if (is_resource($this->stream)) {
62 1
            $this->addPushLogger($logger, $debug);
63
        } else {
64
            throw new ConfigException(t('Error creating logger'));
65
        }
66 1
        $this->logLevel = strtoupper(Config::getParam('log.level', 'NOTICE'));
67 1
    }
68
69 1
    public function __destruct()
70
    {
71 1
        fclose($this->stream);
72 1
    }
73
74
    /**
75
     * @param string $logger
76
     * @param boolean $debug
77
     * @throws \Exception
78
     */
79 1
    private function addPushLogger($logger, $debug)
80
    {
81 1
        $this->logger = new Monolog(strtoupper($logger));
82 1
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
83 1
        if ($debug) {
84 1
            $phpFireLog = Config::getParam('logger.phpFire');
85 1
            if (!empty($phpFireLog)) {
86 1
                $this->logger->pushHandler(new FirePHPHandler());
87
            }
88 1
            $memoryLog = Config::getParam('logger.memory');
89 1
            if (!empty($memoryLog)) {
90 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
91
            }
92
        }
93 1
        $this->uuid = new UidProcessor();
94 1
        $this->logger->pushProcessor($this->uuid);
95 1
    }
96
97
    /**
98
     * @param array $args
99
     * @return array
100
     * @throws exception\GeneratorException
101
     */
102 1
    private function setup(array $args = [])
103
    {
104 1
        $args = $args ?? [];
105 1
        $debug = Config::getParam('debug');
106 1
        $namespace = self::DEFAULT_NAMESPACE;
107 1
        if (0 !== count($args)) {
108 1
            $namespace = $args[0][0] ?? 'PSFS';
109 1
            $debug = $args[0][1] ?? true;
110
        }
111 1
        $path = $this->createLoggerPath();
112 1
        return array($this->cleanLoggerName($namespace), $debug, $path);
113
    }
114
115
    /**
116
     * @return string
117
     */
118 1
    private function setLoggerName()
119
    {
120 1
        $logger = Config::getParam('platform.name', self::DEFAULT_NAMESPACE);
121 1
        $logger = $this->cleanLoggerName($logger);
122 1
        return $logger;
123
    }
124
125
    /**
126
     * @param $logger
127
     *
128
     * @return mixed
129
     */
130 1
    private function cleanLoggerName($logger)
131
    {
132 1
        $logger = str_replace(' ', '', $logger);
133 1
        $logger = preg_replace("/\\\\/", ".", $logger);
134 1
        return $logger;
135
    }
136
137
    /**
138
     * @return string
139
     * @throws exception\GeneratorException
140
     */
141 1
    private function createLoggerPath()
142
    {
143 1
        $logger = $this->setLoggerName();
144 1
        $path = LOG_DIR . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
145 1
        GeneratorHelper::createDir($path);
146 1
        return $path;
147
    }
148
149
    /**
150
     * @param string $msg
151
     * @param int $type
152
     * @param array $context
153
     * @param boolean $force
154
     * @return bool
155
     */
156 22
    public function addLog($msg, $type = \Monolog\Logger::NOTICE, array $context = [], $force = false)
157
    {
158 22
        return $this->checkLogLevel($type) || $force ? $this->logger->addRecord($type, $msg, $this->addMinimalContext($context)) : true;
159
    }
160
161
    /**
162
     * @param int $level
163
     * @return bool
164
     */
165 22
    private function checkLogLevel($level = \Monolog\Logger::NOTICE)
166
    {
167 22
        switch ($this->logLevel) {
168 22
            case 'DEBUG':
169
                $logPass = Monolog::DEBUG;
170
                break;
171 22
            case 'INFO':
172
                $logPass = Monolog::INFO;
173
                break;
174
            default:
175 22
            case 'NOTICE':
176 22
                $logPass = Monolog::NOTICE;
177 22
                break;
178
            case 'WARNING':
179
                $logPass = Monolog::WARNING;
180
                break;
181
            case 'ERROR':
182
                $logPass = Monolog::ERROR;
183
                break;
184
            case 'CRITICAL':
185
                $logPass = Monolog::CRITICAL;
186
                break;
187
        }
188 22
        return $logPass <= $level;
189
    }
190
191
    /**
192
     * @param string $msg
193
     * @param int $type
194
     * @param array $context
195
     * @param bool $force
196
     */
197 22
    public static function log($msg, $type = LOG_DEBUG, array $context = null, $force = false)
198
    {
199 22
        if (null === $context) {
200 20
            $context = [];
201
        }
202 22
        if (Config::getParam('profiling.enable') && 'DEBUG' === Config::getParam('log.level', 'NOTICE')) {
203
            Inspector::stats($msg, Inspector::SCOPE_DEBUG);
204
        }
205
        switch ($type) {
206 22
            case LOG_DEBUG:
207 19
                self::getInstance()->addLog($msg, \Monolog\Logger::DEBUG, $context, $force);
208 19
                break;
209 6
            case LOG_WARNING:
210 2
                self::getInstance()->addLog($msg, \Monolog\Logger::WARNING, $context, $force);
211 2
                break;
212 5
            case LOG_CRIT:
213 1
                if (Config::getParam('log.slack.hook')) {
214
                    SlackHelper::getInstance()->trace($msg, '', '', $context, $force);
215
                }
216 1
                self::getInstance()->addLog($msg, \Monolog\Logger::CRITICAL, $context, $force);
217 1
                break;
218 5
            case LOG_ERR:
219 4
                self::getInstance()->addLog($msg, \Monolog\Logger::ERROR, $context, $force);
220 4
                break;
221 2
            case LOG_INFO:
222 2
                self::getInstance()->addLog($msg, \Monolog\Logger::INFO, $context, $force);
223 2
                break;
224
            default:
225 1
                self::getInstance()->addLog($msg, \Monolog\Logger::NOTICE, $context, $force);
226 1
                break;
227
        }
228 22
    }
229
230
    /**
231
     * @param bool $debug
232
     * @return StreamHandler
233
     * @throws \Exception
234
     */
235 1
    private function addDefaultStreamHandler($debug = false)
236
    {
237
        // the default date format is "Y-m-d H:i:s"
238 1
        $dateFormat = 'Y-m-d H:i:s.u';
239
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
240 1
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
241
        // finally, create a formatter
242 1
        $formatter = new LineFormatter($output, $dateFormat);
243 1
        $stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING);
244 1
        $stream->setFormatter($formatter);
245 1
        return $stream;
246
    }
247
248
    /**
249
     * @param array $context
250
     * @return array
251
     */
252 5
    private function addMinimalContext(array $context = [])
253
    {
254 5
        $context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow';
255 5
        $context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow';
256 5
        if (null !== $_SERVER && array_key_exists('HTTP_X_PSFS_UID', $_SERVER)) {
257
            $context['uid'] = $_SERVER['HTTP_X_PSFS_UID'];
258
        }
259 5
        return $context;
260
    }
261
262
    /**
263
     * @return string
264
     */
265 1
    public function getLogUid()
266
    {
267 1
        return $this->uuid->getUid();
268
    }
269
270
    /**
271
     * @return string
272
     */
273 1
    public static function getUid()
274
    {
275 1
        return self::getInstance()->getLogUid();
276
    }
277
}
278