Passed
Push — master ( 7b2a98...25cc44 )
by Fran
114:22
created

Logger::checkLogLevel()   B

Complexity

Conditions 7
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 15.4039

Importance

Changes 0
Metric Value
cc 7
nc 3
nop 1
dl 0
loc 12
ccs 4
cts 9
cp 0.4444
crap 15.4039
rs 8.8333
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
        $config = Config::getInstance();
56 2
        $args = func_get_args();
57 2
        list($logger, $debug, $path) = $this->setup($config, $args);
58 2
        $this->stream = fopen($path . DIRECTORY_SEPARATOR . date('Ymd') . '.log', 'a+');
59 2
        $this->addPushLogger($logger, $debug, $config);
60 2
        $this->logLevel = Config::getParam('log.level', 'NOTICE');
61 2
    }
62
63 1
    public function __destruct()
64
    {
65 1
        fclose($this->stream);
66 1
    }
67
68
    /**
69
     * @param string $logger
70
     * @param boolean $debug
71
     * @param Config $config
72
     * @throws \Exception
73
     */
74 2
    private function addPushLogger($logger, $debug, Config $config)
75
    {
76 2
        $this->logger = new Monolog(strtoupper($logger));
77 2
        $this->logger->pushHandler($this->addDefaultStreamHandler($debug));
78 2
        if ($debug) {
79 2
            $phpFireLog = $config->get('logger.phpFire');
80 2
            if (!empty($phpFireLog)) {
81 1
                $this->logger->pushHandler(new FirePHPHandler());
82
            }
83 2
            $memoryLog = $config->get('logger.memory');
84 2
            if (!empty($memoryLog)) {
85 1
                $this->logger->pushProcessor(new MemoryUsageProcessor());
86
            }
87
        }
88 2
        $this->uuid = new UidProcessor();
89 2
        $this->logger->pushProcessor($this->uuid);
90 2
    }
91
92
    /**
93
     * @param Config $config
94
     * @param array $args
95
     * @return array
96
     * @throws exception\GeneratorException
97
     */
98 2
    private function setup(Config $config, array $args = [])
99
    {
100 2
        $args = $args ?? [];
101 2
        $debug = $config->getDebugMode();
102 2
        $namespace = self::DEFAULT_NAMESPACE;
103 2
        if (0 !== count($args)) {
104 2
            $namespace = $args[0][0] ?? 'PSFS';
105 2
            $debug = $args[0][1] ?? true;
106
        }
107 2
        $path = $this->createLoggerPath($config);
108 2
        return array($this->cleanLoggerName($namespace), $debug, $path);
109
    }
110
111
    /**
112
     * @param Config $config
113
     *
114
     * @return string
115
     */
116 2
    private function setLoggerName(Config $config)
117
    {
118 2
        $logger = $config->get('platform.name') ?: self::DEFAULT_NAMESPACE;
119 2
        $logger = $this->cleanLoggerName($logger);
120
121 2
        return $logger;
122
    }
123
124
    /**
125
     * @param $logger
126
     *
127
     * @return mixed
128
     */
129 2
    private function cleanLoggerName($logger)
130
    {
131 2
        $logger = str_replace(' ', '', $logger);
132 2
        $logger = preg_replace('/\\\/', ".", $logger);
133
134 2
        return $logger;
135
    }
136
137
    /**
138
     * @param Config $config
139
     * @return string
140
     * @throws exception\GeneratorException
141
     */
142 2
    private function createLoggerPath(Config $config)
143
    {
144 2
        $logger = $this->setLoggerName($config);
145 2
        $path = LOG_DIR . DIRECTORY_SEPARATOR . $logger . DIRECTORY_SEPARATOR . date('Y') . DIRECTORY_SEPARATOR . date('m');
146 2
        GeneratorHelper::createDir($path);
147
148 2
        return $path;
149
    }
150
151
    /**
152
     * @param string $msg
153
     * @param int $type
154
     * @param array $context
155
     * @return bool
156
     */
157 22
    public function addLog($msg, $type = \Monolog\Logger::NOTICE, array $context = []) {
158 22
        return $this->checkLogLevel($type) ? $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 22
        switch($this->logLevel) {
167
            case 'DEBUG': $logPass = Monolog::DEBUG; break;
168
            case 'INFO': $logPass = Monolog::INFO; break;
169
            default:
170 22
            case 'NOTICE': $logPass = Monolog::NOTICE; break;
171
            case 'WARNING': $logPass = Monolog::WARNING; break;
172
            case 'ERROR': $logPass = Monolog::ERROR; break;
173
            case 'CRITICAL': $logPass = Monolog::CRITICAL; break;
174
        }
175 22
        return $logPass <= $level;
176
    }
177
178
    /**
179
     * @param string $msg
180
     * @param int $type
181
     * @param array $context
0 ignored issues
show
Documentation introduced by
Should the type for parameter $context not be null|array? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
182
     */
183 22
    public static function log($msg, $type = LOG_DEBUG, array $context = null)
184
    {
185 22
        if(null === $context) {
186 22
            $context = [];
187
        }
188 22
        if(Config::getParam('profiling.enable')) {
189 1
            Inspector::stats($msg);
190
        }
191
        switch ($type) {
192 22
            case LOG_DEBUG:
193 21
                self::getInstance()->addLog($msg, \Monolog\Logger::DEBUG, $context);
194 21
                break;
195 7
            case LOG_WARNING:
196 2
                self::getInstance()->addLog($msg, \Monolog\Logger::WARNING, $context);
197 2
                break;
198 7
            case LOG_CRIT:
199 1
                if(Config::getParam('log.slack.hook')) {
200
                    SlackHelper::getInstance()->trace($msg, '', '', $context);
201
                }
202 1
                self::getInstance()->addLog($msg, \Monolog\Logger::CRITICAL, $context);
203 1
                break;
204 7
            case LOG_ERR:
205 4
                self::getInstance()->addLog($msg, \Monolog\Logger::ERROR, $context);
206 4
                break;
207 4
            case LOG_INFO:
208 4
                self::getInstance()->addLog($msg, \Monolog\Logger::INFO, $context);
209 4
                break;
210
            default:
211 1
                self::getInstance()->addLog($msg, \Monolog\Logger::NOTICE, $context);
212 1
                break;
213
        }
214 22
    }
215
216
    /**
217
     * @param bool $debug
218
     * @return StreamHandler
219
     * @throws \Exception
220
     */
221 2
    private function addDefaultStreamHandler($debug = false)
222
    {
223
        // the default date format is "Y-m-d H:i:s"
224 2
        $dateFormat = 'Y-m-d H:i:s.u';
225
        // the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
226 2
        $output = "[%datetime%] [%channel%:%level_name%]\t%message%\t%context%\t%extra%\n";
227
        // finally, create a formatter
228 2
        $formatter = new LineFormatter($output, $dateFormat);
229 2
        $stream = new StreamHandler($this->stream, $debug ? Monolog::DEBUG : Monolog::WARNING);
230 2
        $stream->setFormatter($formatter);
231 2
        return $stream;
232
    }
233
234
    /**
235
     * @param array $context
236
     * @return array
237
     */
238 5
    private function addMinimalContext(array $context = [])
239
    {
240 5
        $context['uri'] = null !== $_SERVER && array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : 'Unknow';
241 5
        $context['method'] = null !== $_SERVER && array_key_exists('REQUEST_METHOD', $_SERVER) ? $_SERVER['REQUEST_METHOD'] : 'Unknow';
242 5
        if(null !== $_SERVER && array_key_exists('HTTP_X_PSFS_UID', $_SERVER)) {
243
            $context['uid'] = $_SERVER['HTTP_X_PSFS_UID'];
244
        }
245 5
        return $context;
246
    }
247
248
    /**
249
     * @return string
250
     */
251
    public function getLogUid() {
252
        return $this->uuid->getUid();
253
    }
254
255
    /**
256
     * @return string
257
     */
258
    public static function getUid() {
259
        return self::getInstance()->getLogUid();
260
    }
261
}
262