Test Failed
Push — master ( cd3718...faedb3 )
by Fran
03:03
created

Logger::addDefaultStreamHandler()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 1
nop 1
dl 0
loc 11
ccs 7
cts 7
cp 1
crap 2
rs 10
c 0
b 0
f 0
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\types\helpers\GeneratorHelper;
13
use PSFS\base\types\helpers\Inspector;
14
use PSFS\base\types\helpers\SlackHelper;
15
use PSFS\base\types\traits\SingletonTrait;
16
17
18
if (!defined('LOG_DIR')) {
19
    GeneratorHelper::createDir(BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
20
    define('LOG_DIR', BASE_DIR . DIRECTORY_SEPARATOR . 'logs');
21
}
22
23
/**
24
 * Class Logger
25
 * @package PSFS\base
26
 * Servicio de log
27
 */
28
class Logger
29
{
30
    const DEFAULT_NAMESPACE = 'PSFS';
31
    use SingletonTrait;
32
    /**
33
     * @var \Monolog\Logger
34
     */
35
    protected $logger;
36
    /**
37
     * @var resource
38
     */
39
    private $stream;
40
    /**
41
     * @var UidProcessor
42
     */
43
    private $uuid;
44
    /**
45
     * @var string
46
     */
47
    protected $logLevel;
48
49
    /**
50
     * Logger constructor.
51
     * @throws exception\GeneratorException
52
     */
53 2
    public function __construct()
54
    {
55 2
        $args = func_get_args();
56 2
        list($logger, $debug, $path) = $this->setup($args);
57 2
        $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...
58 2
        $this->addPushLogger($logger, $debug);
59 2
        $this->logLevel = Config::getParam('log.level', 'NOTICE');
60 2
    }
61
62 1
    public function __destruct()
63
    {
64 1
        fclose($this->stream);
65 1
    }
66
67
    /**
68
     * @param string $logger
69
     * @param boolean $debug
70
     * @throws \Exception
71
     */
72 2
    private function addPushLogger($logger, $debug)
73
    {
74 2
        $this->logger = new Monolog(strtoupper($logger));
75 2
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
76 2
        if ($debug) {
77 2
            $phpFireLog = Config::getParam('logger.phpFire');
78 2
            if (!empty($phpFireLog)) {
79 1
                $this->logger->pushHandler(new FirePHPHandler());
80
            }
81 2
            $memoryLog = Config::getParam('logger.memory');
82 2
            if (!empty($memoryLog)) {
83 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
84
            }
85
        }
86 2
        $this->uuid = new UidProcessor();
87 2
        $this->logger->pushProcessor($this->uuid);
88 2
    }
89
90
    /**
91
     * @param array $args
92
     * @return array
93
     * @throws exception\GeneratorException
94
     */
95 2
    private function setup(array $args = [])
96
    {
97 2
        $args = $args ?? [];
98 2
        $debug = Config::getParam('debug');
99 2
        $namespace = self::DEFAULT_NAMESPACE;
100 2
        if (0 !== count($args)) {
101 2
            $namespace = $args[0][0] ?? 'PSFS';
102 2
            $debug = $args[0][1] ?? true;
103
        }
104 2
        $path = $this->createLoggerPath();
105 2
        return array($this->cleanLoggerName($namespace), $debug, $path);
106
    }
107
108
    /**
109
     * @return string
110
     */
111 2
    private function setLoggerName()
112
    {
113 2
        $logger = Config::getParam('platform.name', self::DEFAULT_NAMESPACE);
114 2
        $logger = $this->cleanLoggerName($logger);
115
116 2
        return $logger;
117
    }
118
119
    /**
120
     * @param $logger
121
     *
122
     * @return mixed
123
     */
124 2
    private function cleanLoggerName($logger)
125
    {
126 2
        $logger = str_replace(' ', '', $logger);
127 2
        $logger = preg_replace('/\\\/', ".", $logger);
128
129 2
        return $logger;
130
    }
131
132
    /**
133
     * @return string
134
     * @throws exception\GeneratorException
135
     */
136 2
    private function createLoggerPath()
137
    {
138 2
        $logger = $this->setLoggerName();
139 2
        $path = LOG_DIR . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
140 2
        GeneratorHelper::createDir($path);
141
142 2
        return $path;
143
    }
144
145
    /**
146
     * @param string $msg
147
     * @param int $type
148
     * @param array $context
149
     * @param boolean $force
150
     * @return bool
151
     */
152 23
    public function addLog($msg, $type = \Monolog\Logger::NOTICE, array $context = [], $force = false) {
153 23
        return $this->checkLogLevel($type) || $force ? $this->logger->addRecord($type, $msg, $this->addMinimalContext($context)) : true;
154
    }
155
156
    /**
157
     * @param int $level
158
     * @return bool
159
     */
160 23
    private function checkLogLevel($level = \Monolog\Logger::NOTICE) {
161 23
        switch($this->logLevel) {
162
            case 'DEBUG': $logPass = Monolog::DEBUG; break;
163
            case 'INFO': $logPass = Monolog::INFO; break;
164
            default:
165 23
            case 'NOTICE': $logPass = Monolog::NOTICE; break;
166
            case 'WARNING': $logPass = Monolog::WARNING; break;
167
            case 'ERROR': $logPass = Monolog::ERROR; break;
168
            case 'CRITICAL': $logPass = Monolog::CRITICAL; break;
169
        }
170 23
        return $logPass <= $level;
171
    }
172
173
    /**
174
     * @param string $msg
175
     * @param int $type
176
     * @param array $context
177
     * @param bool $force
178
     */
179 23
    public static function log($msg, $type = LOG_DEBUG, array $context = null, $force = false)
180
    {
181 23
        if(null === $context) {
182 23
            $context = [];
183
        }
184 23
        if(Config::getParam('profiling.enable') && 'DEBUG' === Config::getParam('log.level', 'NOTICE')) {
185
            Inspector::stats($msg);
186
        }
187
        switch ($type) {
188 23
            case LOG_DEBUG:
189 22
                self::getInstance()->addLog($msg, \Monolog\Logger::DEBUG, $context, $force);
190 22
                break;
191 7
            case LOG_WARNING:
192 2
                self::getInstance()->addLog($msg, \Monolog\Logger::WARNING, $context, $force);
193 2
                break;
194 7
            case LOG_CRIT:
195 1
                if(Config::getParam('log.slack.hook')) {
196
                    SlackHelper::getInstance()->trace($msg, '', '', $context, $force);
197
                }
198 1
                self::getInstance()->addLog($msg, \Monolog\Logger::CRITICAL, $context, $force);
199 1
                break;
200 7
            case LOG_ERR:
201 4
                self::getInstance()->addLog($msg, \Monolog\Logger::ERROR, $context, $force);
202 4
                break;
203 4
            case LOG_INFO:
204 4
                self::getInstance()->addLog($msg, \Monolog\Logger::INFO, $context, $force);
205 4
                break;
206
            default:
207 1
                self::getInstance()->addLog($msg, \Monolog\Logger::NOTICE, $context, $force);
208 1
                break;
209
        }
210 23
    }
211
212
    /**
213
     * @param bool $debug
214
     * @return StreamHandler
215
     * @throws \Exception
216
     */
217 2
    private function addDefaultStreamHandler($debug = false)
218
    {
219
        // the default date format is "Y-m-d H:i:s"
220 2
        $dateFormat = 'Y-m-d H:i:s.u';
221
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
222 2
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
223
        // finally, create a formatter
224 2
        $formatter = new LineFormatter($output, $dateFormat);
225 2
        $stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING);
226 2
        $stream->setFormatter($formatter);
227 2
        return $stream;
228
    }
229
230
    /**
231
     * @param array $context
232
     * @return array
233
     */
234 5
    private function addMinimalContext(array $context = [])
235
    {
236 5
        $context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow';
237 5
        $context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow';
238 5
        if(null !== $_SERVER && array_key_exists('HTTP_X_PSFS_UID', $_SERVER)) {
239
            $context['uid'] = $_SERVER['HTTP_X_PSFS_UID'];
240
        }
241 5
        return $context;
242
    }
243
244
    /**
245
     * @return string
246
     */
247 1
    public function getLogUid() {
248 1
        return $this->uuid->getUid();
249
    }
250
251
    /**
252
     * @return string
253
     */
254 1
    public static function getUid() {
255 1
        return self::getInstance()->getLogUid();
256
    }
257
}
258